In my last post I lamented not having access native iOS features such Game Center and single sign-on Twitter. Well, Milkman Games has come to the rescue with their Game Center Native Extension for Adobe AIR. Took me less than an hour to pop it in to my FlashDevelop project, connect all the events and go. All in AS3, no Mac or Xcode required. Post scores, view achievements, all that good stuff with minimal effort. They also have an Android AdMob extension and more on the way – valuable tools for running AIR on mobile devices.
I’ve got Word Up Dog now running with Game Center on iPads and iPhone 4+, but I need to test it on the iPhone 3GS and iPod Touch 3+. So this is a call for testers – please sign up to join my Test Flight team if you’ve got any iOS device, and I may recruit you to help me test Word Up Dog, Rebuild, or some future game.
For anyone who played the old flash version of Word Up Dog, there’s going to be some changes. I’m spicing up the levels with some new terrain and new powerups. I know, it’s no Rebuild, but after writing about zombies for four months I need some cute animals talking in urban slang stereotypes.
Word Up Dog was always meant to be an iOS game, so here we go!
I’d already optimized my new Flash game Word Up Dog to run on mobile phones, and used Air to package a version that I could sell in the Android app store. Now for the next challenge: the iPhone.
Shortly after Adobe announced the tools for compiling Flash code into iOS apps, Apple banned the process as part of their ongoing spat with Adobe. Happily they retracted this bit of bs six months later, so we are free to experiment with Air for iOS once more. God knows if we’ll ever view Flash websites on an iPad browser, but this is a start.
Building Air for the iPhone is similar to the Android process, but generating the security certificate requires paying Apple $99 for a developer license (Android is free), then dancing back and forth uploading and downloading files from their website. Although you need a Mac to write iOS apps in Objective-C, you can compile Flash AS3 code into iOS using Mac, Windows, or Linux. I used Windows, along with OpenSSL (instead of Keychain) to generate the security bits, and iTunes (instead of Xcode) to install the app onto my phone.
Here are the steps:
Download the Air 2.6 SDK, paste it into a copy of your Flex SDK directory, and set FlashDevelop to compile using the result
Generate a key by calling openssl genrsa -out SarahNorthway.key 2048
Generate a certificate signing request with openssl req -new -key SarahNorthway.key -out WordDog.certSigningRequest -subj “/emailAddress=youremail@domain.com, CN=Your Name, C=US”
On the Apple website, upload WordDog.certSigningRequest, create a provisioning profile for your iPhone and download WordDog.mobileprovision and developer_identity.cer
Generate a pem file with openssl x509 -in developer_identity.cer -inform DER -out developer_identity.pem -outform PEM
Generate the p12 certificate with openssl pkcs12 -export -inkey SarahNorthway.key -in developer_identity.pem -out WordDog.p12 -passout pass:yourpass
Build your air project to create WordDog.swf
Compile the final ipa file using adt -package -target ipa-app-store -provisioning-profile WordDog.mobileprovision -storetype pkcs12 -keystore WordDog.p12 -storepass yourpass WordDog.ipa application.xml -C . WordDog.swf Default.png iconsFolder (this takes a few minutes)
In iTunes, drag WordDog.mobileprovision and WordDog.ipa into the library
Find your game in the iTunes library apps, drag it onto your phone and sync
Wheuf! A few extra steps and security files in there, but it’s all worth it, so we can sleep safe knowing nobody is installing homebrew apps on their own iPhones without paying Apple first.
Unfortunately Air 2.6 only supports iPhone gen 3 and above, but this is probably for the best considering how much more processor intentive the Flash code seems to be compared to Objective-C code. Word Up Dog runs well on a 2nd gen iPad, but it still drops to 15 fps when moving the map around, so I’m going to have to go back to optimization before I can release it on the app store.
Having already optimized my game Word Up Dog so that it runs relatively well in a browser on an Android phone, I was ready to package it up as an installable app. Adobe Air makes this easy to do with few changes to your original code. Adobe has a Flash CS5 plugin to do it, but I prefer to do things the free-and-open way when I can, so here’s how I built the Android app using only FlashDevelop and other free Windows tools.
First, I don’t recommend the Android emulator. I struggled with getting emulator-compatible versions of the Air packager and Air runtimes installed. There didn’t seem to be much advantage so use a phone if you can get your hands on one.
Generate a certificate using adt -certificate -cn WordUpDog 1024-RSA certificate.pfx yourpass
Build your air project to create WordUpDog.swf
Package the swf into an apk file with adt -package -target apk -storetype pkcs12 -keystore certificate.pfx -storepass yourpass WordUpDog.apk application.xml -C . WordUpDog.swf iconsFolder
Upload WordUpDog.apk to your phone and baby, you’ve got a stew going
I was prompted to install the Air interpreter the first time I ran the game on my Nexus One, then it behaved just like any other app. The performance was about the same as running the SWF through the phone’s browser, but of course there are advantages to being installed. I could force the game to stay in landscape perspective and add a customized handler to deal with incoming phone calls. Not to mention being able to upload and sell it on the Android app store!
I just put my new game Word Up Dog up for bidding on FlashGameLicense. It’s very different from my first game Rebuild (I needed a break from zombies!). In Word Up Dog, you play a dog digging underground for letters to anagram, aided by cute animals who speak in 90’s hiphop lingo. It has a simple interface and can be played in short sessions, so it’s a good fit for mobile platforms like the iPhone, iPad and Android phones.
When uploading a game to FlashGameLicense, one of the options is a “Mobile-ready” checkbox. Here’s what I did to make Word Up Dog mobile ready…
I have a Nexus One Android phone, which unlike the iPhone can run Flash in its browser. So as a first test I pointed it at the totally unoptimized game swf. I was pleased to see the game load quickly and error-free, and the graphics looked good on the bright little screen. The SimpleButtons were easy to hit and the mouse over state even showed briefly. Movement using both the trackball (which fires up/right/down/left KeyboardEvents) and touch worked correctly. But the framerate was crappy, and touching even a blank area on the screen brought the game to a crawl.
First, I looked at how I was rendering the map, a 800×550 sprite containing ~150 vector shape tiles. The tiles had cacheAsBitmap=true which had a noticeable effect on my pc, but it was hard to tell if it was doing anything on Android. Instead I manually drew each of the tiles to a Bitmap, which improved the framerate significantly. Drawing all the tiles onto one huge 800×550 bitmap was even better, but the way my tiles overlap made updating (by blitting) difficult.
I improved the movement speed by jumping the screen from square to square instead of smoothly scrolling it. I downgraded the target fps from 30 to 24, and simplified the gui animations so that instead of fading in, notice text pops into existance. I replaced contrast, emboss and drop shadow filters with graphical approximations. I cached the dog’s shape tween animations as Bitmaps using TouchMyPixel’s AnimationCache. Each of these things had a small but helpful effect on the framerate.
Now to tackle the touch issue. Holding down on any part of the screen lowered the framerate by 10fps, even after stripping out all MouseEvents. I couldn’t recreate it on pc (even via air at 250fps) or see evidence of it in a profiler. My guess is that Flash just isn’t very efficient at dealing with touch screens. What finally improved things was setting mouseEnabled=false and/or mouseChildren=false to everything in the game that isn’t meant to be clicked. This seems to be especially important for TextFields.
Finally, memory. The free FlashPreloadProfiler told me I was using 50mb, and showed the number of instances of each class and time in functions. Adobe’s Flash Builder Pro profiler gave me additional info including function stacks and the momeory used by each class.
I got my memory down to 20mb by instantiating some map-related things when they came into view rather than at game start. I verified that I didn’t have any memory leaks such as objects or handlers left around after exiting to menu and starting a new game.
To recap my optimizations:
Draw shapes to Bitmaps instead of relying on cacheAsBitmap
Simplify gui animations
Cache character animations as Bitmaps
Remove filters
Set mouseEnabled=false and/or mouseChildren=false on non-clickables
Other best practices I follow include cutting down on EnterFrame events, avoiding masks, and using strongly-typed variables.
I can now run Word Up Dog on my phone through Chrome at 20-24 fps! Not perfect and it will be slower on older phones, but I’m calling it a success. In my next post I’ll talk about packaging the game up using Air so I can sell it in the Android and iPhone app stores.