Friday, February 17, 2012

Using Flash for in-game animation in an Open-GL based iOS project

We recently released our iOS game Diggin' Dogs, and we decided to keep it under 20mb for 3G downloads on the App Store. Since the game has a fair amount of content there was absolutely no way to use any kind of pre-rendered animated cutscenes for the intro.

Instead, I created a tool to allow us to animate full scenes in Flash, play it back through the game's normal rendering system, and only take up the size of a spritesheet and a few text files of animation data.

There are a few projects floating around that take Flash animation through some similar kind of conversion, but as far as I've been able to find, the approach I took seems to be different to the norm.

Instead of parsing a .fla or .swf file directly, I play through a swf in real-time and record where everything is. In a nutshell, it works by starting at the root level and recursively looking for DisplayObjects, and then DisplayObjects inside those DisplayObjects, and so on until it runs out of stuff to find, each frame.

Every named instance is recorded into an individual frame's spritelist with its x, y, rotation, scale, and alpha. If an object is found inside another object, the parent transform values are (recursively) added/multiplied to its own values, so that the game engine needs only place and render a flattened scene during playback.

For simplicity, I opted to take this approach instead of saving and later parsing the DisplayObject hierarchy, but there's no reason it couldn't be modified to store parent-chains as well.

At the moment it's very crude, and it's probably worth noting the downsides first of all:
  • currently, an enormous amount of data is generated, which then puts a notable load on the CPU to untangle later as it loads a scene into memory. I plan to do a lot of extra conversion from raw data patterns to expressions and similar things, but it's difficult to say whether this issue will ever really be completely fixable
  • each movieclip in Flash must be a distinct and simple representation of a sprite in the engine - no graphics, shapes, or anything else set in the IDE that can't be detected in a swf at runtime.
  • no masking
  • instance name mistakes severely break the system
  • flipped movieclips can sometimes be unreliable to detect (the flipping, that is)
  • correct depth sorting on the other end can be very troublesome and has to be well planned
But while these things did turn a normal Flash animation process into a somewhat annoying one, it does work on the other end, and I was happy with the results. There are also some particularly nice upshots from this process that are worth mentioning:
  • because the transformation data is logged per object per frame as it plays, the conversion system makes no distinction at all between timeline key-framed animation and code-driven animation scripted in Flash. This could just be some stop commands and gotoAndPlay commands, or it could mean a huge elaborate actionscripted sequence. 
  • It'll log/convert anything that happens interactively during the course of playback, and if you have random elements at play, you can just keep running it until you have exactly the data you're after.
  • it's easy to code some simple ways to display debug information during playback/conversion to help iron out any unexpected stuff that may be happening when the game engine plays back the animation.
Here's the animated intro for Diggin' Dogs:

The ocean movement is an example of code-driven Flash animation that was just taken frame for frame for the final in-engine playback. At 60fps, the animation actually looks and plays a lot smoother on the iPhone than it does in Flash on my Intel Mac.

I'd love to make this tool available, if at some point I can improve it enough (I cobbled this together in a bit of a hurry). Using it on another project may be all it needs for a good cleanup.

It's an imperfect system, but one I was easily able to use in production, with the intended results achieved.

The other methods of getting Flash animation into some kind of engine are certainly viable as well - a good example being the tools my colleague renderhjs is working on:

I think they'll each have their pros and cons though.

No comments:

Post a Comment