Adobe AIR 3.2 adds the much anticipated Stage 3D to mobile apps. With this comes the ability to use Starling, a great little 2D library built on Stage 3D that closely matches the APIs of the classic Flash Player display list. I’ve been looking for a reason to learn Starling, and I take learning seriously, so that means throwing myself head-first into the development of a complete, real app using Starling. As of today, Rivers of Olympus, my tile-matching game with similarities to Mahjong solitaire, is available on iOS (universal iPad and iPhone), Android, Amazon Kindle Fire, along with the NOOK Tablet and Color. All these versions use Starling and AIR 3.2 captive runtime.
Note: Until RIM adds Stage 3D support, I cannot deploy the Starling version to the BlackBerry PlayBook. The non-Starling version is still available on PlayBook.
My task for the conversion from classic display list consisted of two major parts. First, I needed to make my personal library of mobile UI controls run on Starling. These older “Foxhole” controls were built on
fl.core.UIComponent included with Flash Professional. However, in Starling, I needed to start with a new base class. This meant either porting
UIComponent over to Starling or starting from scratch with something simpler.
I decided to start from scratch and personalize things. In particular, I ripped out the styling system and made all styles in the Starling version into regular getters and setters. This gives me stronger typing and keeps code from getting too messy with all the magic strings that Adobe’s style managers often use. I should be able to build some sort of external style manager that injects styles into each component as they’re added to the display list, if I ever need something like that. For now, it hasn’t been too important. I also simplified the invalidation mechanisms to ensure that all components validate completely each frame. In general, the depth of nesting isn’t too extreme, so I feel pretty safe working like that.
The new Foxhole for Starling mobile UI controls are now on Github. They’re severely lacking in documentation and examples (in other words, there are none). They’re without a default skin too, so some assembly is required. Maybe someone will find them useful, though. I wish I could take some time off to polish them up a bit more for general usage.
Edit: I put together a very basic Getting Started page on the Github wiki. For the curious, it simply shows how to create a Foxhole Button control.
The Rest of the Game
Working on Foxhole for Starling was relatively easy, and I could mostly focus on each component in isolation. However, converting a full game’s codebase to Starling was a more daunting task. Not only did I have the basic Starling conversion of the display list (including changing all text to bitmap fonts), I also had to update the code to use the new APIs in the updated Foxhole controls. This left me working through compile errors one by one, with no ability to run my code for a couple of days. That’s a new and scary experience for me. I’m used to constantly running my code to verify that things are working, and even very ambitious refactoring will give me something I can run (even if buggy) within a couple of hours. Once I finally got it to compile, I ran into immediate runtime errors, so I spent more time tracking down each one until I could get a title screen or something displayed. Since the new Starling-based UI controls were still not fully tested, all this work took much longer, and I found myself switching between both codebases to fix bugs in each.
Overall, the full conversion, including both UI controls and the game itself took about a week, including heavy testing to be sure that I didn’t introduce any new bugs from the differences between the old and new renderers. With the UI controls stabilized now, and more experience in the steps required to do an ambitious conversion like this, I think I can finish the next game in about 3-4 full working days. It’s still not as simple as changing imports from
starling*, but it would be a lot worse if I were using a 2D framework that didn’t match the classic display list so closely. I cannot stress enough how nice it is that Starling matches the display list. Learning is easier, and if you need to convert existing code, it helps so much.
Starling running on Stage 3D is obviously visually smoother than renderMode gpu in my games. Most devices I tested on were consistently running at over 30 frames per second, with many close to 60. Choppy framerates and hiccups, which can be all too common with renderMode gpu, already feel like a thing of the past. My games aren’t super intense, but this seems like a pretty significant improvement that will greatly increase what AIR mobile developers are able to do, especially on some older devices.
That isn’t to say that Starling removes all performance issues. In particular, very slow devices like the NOOK Color still needed some optimization to make things run smoothly. There seems to be a threshold where very, very slow devices have a slightly harder time with Starling than renderMode gpu, if you don’t do some basic optimizations, and then everything else gets a beautiful performance boost even without those improvements.
During testing, I found that the NOOK Color seemed to be rendering somewhat faster than it did with renderMode gpu, but touch events in particular where lagging way behind. I was uploading textures straight from PNGs for basically every single display object, like individual, separate button states. All the textures were staying on the GPU, but swapping between them all became a bottleneck. I needed to combine all my game’s images into a single 2048×2048 texture atlas to fix this. Even after that, if I created a single separate Quad (single-color rectangle) somewhere on the stage, the performance would drop significantly. If I wanted to display the framerate, I had to rewrite parts of this port of mr. doob’s Stats class so that the bitmap font and background would come from my atlas instead of using their own separate textures. It was a little frustrating, but the result was that the game ended up being more responsive than the previous version.
To be clear, these optimizations only applied as requirements on the NOOK Color, and an equally-underpowered Motorola Droid 1, among my various test devices. The original unoptimized code worked flawlessly on the Nexus One, Nexus S, NOOK Tablet, Kindle Fire, iPad 1, and iPhone 3GS. Several of those devices couldn’t keep up with 30fps in renderMode gpu (but were “good enough”), but all were running above 30fps with Starling. The best didn’t quite reach 60fps, like my PC, but a few were in the low to mid-50s consistently, even during tweens that changed the entire screen every frame.
Come on in, Starling
Any game I make with AIR for mobile (and probably Flash Player, but I’m pretty focused on apps these days) from now on will use Starling, for sure. In fact, the performance improvement feels so good that I wish I had the time to port all of my existing games over to Starling. I doubt I would see enough improvements in sales to make it worth my while, though. Still, maybe I’ll have the occasional weekend afternoon to catch up on all that over time. If you’re developing 2D apps for mobile with Adobe AIR, I highly recommend checking out Starling or another 2D framework built on Stage 3D. Between Stage 3D and captive runtime, AIR is finally getting close to a “perfect” rich mobile app solution for my needs. Now if only Adobe offered a way to remove parts of the captive runtime to decrease the final binary size. There’s always just one more thing you wish were better, no matter what technology you use.