Monday, 4 August 2008

Meta4orce: creating 3D Flash games with PaperVision3D

NOTE: I am now a freelance developer, and no longer an employee of Bloc.

Over at Bloc we recently launched Meta4orce, a unique interactive sci-fi TV show which was broadcast on BBC2 and is also available globally via the website. With a story created by legendary comic-book writer Peter Milligan, it's a project I'm very proud to have worked on. When viewed online, the show integrates broadcast quality animation with high quality interactive games. (Please note, it's very much a broadband only site as it features a lot of video, and the games do require a decent PC or Intel Mac to run smoothly). UPDATE: If you want to know even more about the project, I've been answering game design questions over at the excellent Brainy Gamer blog.

We wanted the site to invoke the gritty, futuristic feeling of the show, and also offer a gaming experience that resonated with console gamers. To this end we made extensive use of PaperVision3D, specifically version 2.0, dubbed Great White (at the moment this can only be downloaded via a subversionclient, but these are free and fairly easy to set up). As we did some fairly unusual things with PV3D, I thought it might be useful to document some of the solutions and work-arounds we came up with:

The main user interface is implemented in Papervision3D, and makes extensive use of the MovieMaterial class to map 2D animations onto 3D planes. Developer Mat applied a custom displacement map to the Viewport to create the cool glitch effect. We found that setting the stage quality to LOW is a good way to get a bit of extra performance out of PV3D.

This first-person perspective maze game uses a custom Model View Controller framework to link a 2D maze game mechanic to a Papervision3D view. I initially created the game in a 2D top-down view, then added another View to display the game in 3D. This is probably one of the few times it's actually sensible to use MVC on a Flash game (I think I'll cover this topic in more detail in a future post).

The main technical challenge was to stop PV3D from clipping the walls when they are close to the camera - basically it seems that planes are not drawn if PaperVision thinks any one of their 3 corners is outside the viewing area. I got around this by switching low polygon, 2 triangle plains for high polygon plains when the camera is close to them. I also used a lower resolution texture to render far-away walls. To improve memory usage and general performance, all the animated textures in the maze are created by swapping the BitmapMaterial of a plane every frame, rather than using MovieMaterial - this eliminates a lot of costly copyPixels operations. Again to try and reduce the amount of memory PV3D was using, I implemented a custom object pooling system for textures and geometry - so that walls are re-used between different levels. The levels were created in a simple editor which saved out strings of 1s and 0s, so a basic 4x4 square level might look like "11110011001111".

This tower defence game uses PV3D to render a 3D view of a 2D game mechanic, again using MVC to separate game logic from graphics rendering. The main technical challenge was to stop the towers and enemies clipping strangely with the floor – when 2 polygons are close together they will flicker wildly as PV3D cannot decide which to draw on top of which. I got around this by rendering 2 separate PV3D scenes into 2 separate viewports – one for the interactive (clickable) floor grid, and one for the towers and enemies on top. As this slowed the frame rate dramatically, it only renders the scene every other frame, so while the game logic and user interface run at 30 frames per second, the 3D graphics effectively render at 15fps.

3D artist Matt modelled the defence towers in Maya and then opened in Blender and exported to ActionScript classes. PaperVision models have to be very low polygon if you want your game to run at all smoothly! To improve performance, the enemies are pre rendered animations mapped onto transparent 2 triangle plains, which are set to point at the camera every frame using PV3D's "lookAt" function (I couldn’t find a native “billboard” or “sprite” class in PV3D to handle this effect – I’m sure one must exist somewhere though - I know Away3D has them).

In this game the player looks for clues beneath the waves of a flooded London street. For this game, developer / 3D guy Mark modelled a scene in Blender and exported the parts as AS classes. Unlike some of the other Meta4orce games, we didn’t use an MVC pattern – we directly control the camera in the scene using PV3D's built-in functions like moveForward, pitch, roll etc. This game also uses MovieMaterial for animation and 2D planes pointed at the camera to create the illusion of 3D objects. The built-in virtual mouse in PV3D makes it really easy to add interaction such as rollovers to 3D objects. This is one of PV3D's best points. Camera clipping was again a problem on this game, so we don’t allow the player to get too close to the walls or floor.

This 3rd person perspective maze game is implemented in a similar way to Deadsphere Pt. I and Shock to the system, with an MVC pattern, and all the game logic separated from the PV3D view. One cool thing on all the MVC games is that the sound is all handled as if it were another "view" onto the game "model", so none of the game classes need a reference to the sound code, or even know that sound exists. This kind of "loose coupling" is considered good practice in object oriented programming.

The avatar you control is very subtly animated by swapping between 10 separate models representing the frames of animation. This is a very inefficient method of animation that we wouldn’t recommend anyone else use (especially as it’s almost too subtle to notice anyway!). For future projects I definitely look forward to a work flow where 3D animation can easily be brought from Maya to Flash, maybe with "bones" (I’m sure someone is working on this if it doesn’t exist already).

This is really just an extension of the Mako user interface, with simple 2D mini-games rendered onto PV3D planes using MovieMaterial. We made sure to use the “animated” property very sparingly, to stop PV3D redrawing materials unnecessarily, as that was the main source of slow down. Also, when the games are full screen, they are removed from PaperVision and added to the main stage, as interactivity is more stable and fully featured this way.

We did some neat things on this project - one cool thing is that while you're playing the game we're buffering the next video in the background, so it's ready to watch when you finish playing. Please go and play with the site and tell me what you think - personally I love it, but understand that it's not to everybody's tastes (some people don't like sci-fi, some people don't like websites that use a lot of CPU and memory, etc etc). Either way, we achieved a lot and made PaperVision3D do some things it didn't want to, so it's all good!

@noelb - thanks man, I'd say each game took 1 developer an average of about 3-4 weeks. As there were 2 developers working at any one time, we finished the whole project in about 4 months, including all 8 games, the menus and video player etc. Definitely the longest development cycle I've ever had! (The animation team finished their 28 minutes of broadcast quality animation in the same time period - god knows how they did it!)

In some places we were able to re-use some of the code - for example the maze games and the tower defence game shared a lot, but some things took longer, like writing the mode7 racing game engine from scratch. I'd barely played with PaperVision3D at the start of the project by the way, so learning curves a plenty mixed in there too!

First off all, congratulations on an AWESOME job. It's great to see our baby being used like this and you really did a great job implementing the engine.

I have one comment though. The Billboard / Sprite class is actually present, in the form of the Particle class. This will actually allow you to have Sprite like functionality, if you use a BitmapParticleMaterial on it.

would you like to share your secret on how you did the video thumbnails whilst it's playing? are they just all stored in memory as it's playing... or is one dynamically generated as you select a position?

Of course! We take a freeze-frame of the video in the main window and place it over the top of the video itself. Underneath this the video is still playing/scrubbing! We then copy the bitmap from the hidden video to the thumbnail. No secret!

@pablo - the "model" of the game engine is essentially 2D top-down. The PaperVision is just a view onto that game - I never use the PaperVision models to test collisions. The test is done using basic 2D collision detection.