Showing posts with label flash. Show all posts
Showing posts with label flash. Show all posts

Tuesday, August 21, 2012

Automating the process of converting AS3 to Objective C

I’ve done a number of iOS games now that borrowed elements from an older Flash/AS3 counterpart, often leveraging large portions of code that could be converted rather than re-written.

Code conversion is a menial, laborious, and fairly uninteresting task, but you take any time savers you can. When I’ve written code that works, rewriting it by hand on another platform is more of a drag than a bit of syntax wrangling.

Needless to say, there are many hours of swapping “var x:Thing” declarations, moving ivars into headers and their default values into .m inits, then the methods; () to [] - even more time consuming when I bother to use the descriptive method style in obj c, which I generally do. Subtle pattern swapping, none of it difficult, just a hell of a lot of it.

Until now I’ve had projects small enough (at least in transferred code-volume terms) that I’ve been able to stand the manual work, but my latest Flash game finally put me over the tipping point.

I spent a little time on a tool to take care of the menial changes - nothing too advanced yet, but already very helpful.

Here’s an example conversion:

original class
.h output


.m output







What it does so far:

  •  all variable declarations converted to obj c style - atomic types detected first, then pointer/object style assumed for anything else.
  • find public instance variables, declare them in the header and set up @property/synthesize
  • private/protected variables found and added to header
  • all instance variables declared in header are given their default values in the -(id)init method of the .m, or NULL/false/0 if none was specified in the AS3 class.
  • find static variables and recreate them in the .m (doesn’t yet create external access in the case of things that were public static)
  • convert all class methods to objective C syntax - build descriptive methods where more than one parameter exists
  • replace math calls - e.g. Math.floor() -- floorf()
  • identify method calls on this/self and replace syntax (currently very limited - I’ve only coded this to respond to calls without parameters so far as this area gets a bit more complex)


what it doesn’t do yet (or maybe ever):

  • method calls on objects - e.g. instanceOfThing.doSomething() - is left alone. This simple example would be ok - but looking at another example: instanceOfThing.getSubThingMatching(banana.whatColourAmI(UniverseConstants.ON_TUESDAYS)).x = 5; ...it’s kind of getting deeper than I really need to go for my purposes.
  • object/instance creation e.g. var a:Thing = new Thing(); - I think I’ll probably add this, at least just with a default [[alloc] init] case that should be ok a lot of the time.
  • various other edge-cases I haven’t gotten to, and probably lots I’ve forgotten.


So that’s about it so far. Already very handy for my current project

With a little more work and some tidying up, it may possibly make it’s way into shoebox as a droplet tool. Currently in testing, you can drop a .as file on and be given .h and .m files in the source directory.

I’m undecided as to whether it’d be worth the trouble of loading a full directory and exploring an entire class hierarchy to better convert method calls and the like - would be a fun challenge, but total overkill.

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.