Yes indeed, Frozen Fractal’s first officially released game is there! It’s called Patchy, and it’s a retro arcade-style land-grabbing game for Android. This post is about its inception and also describes some bits of the technical implementation.
Patchy is the spiritual successor to my one-weekend Ludum Dare entry Park to Park. (And of course, Park to Park is itself a spiritual successor to the 1981 arcade game Qix.) But I made several important changes.
The original Qix and also Park to Park let you move only horizontally and vertically. This makes sense with keyboard controls. With the freedom of a touch screen however, allowing for movement in any direction is much more fun. It also makes the bouncers’ trajectory harder to predict.
In Qix, the player’s movement is restricted to previously drawn edges. I saw no need for that and thought it might be hard to control on a touch screen, so I let the player move anywhere they please outside the arena.
The other notable change was that I added the tracers, which traverse the edge of the arena. These are critical to fast gameplay, because without them, you can just wait forever on the edge until a good opportunity arises. Because the player is not confined to edges, the tracers needed to have their laser sword to increase their range. Their purpose is to force the player to go out into the arena and expose themselves to danger, and they fulfil that purpose quite effectively!
I chose to use libgdx, a cross-platform game library originally developed for Android. The great advantage of libgdx is that you can run the very same game on desktop Java, so there is no need for slow emulators or annoying apk installs. The result is a much faster development cycle. I highly recommend it.
Anyway, one long Easter weekend of coding later, I had a game. A game with horrible, Ludum Dare style code quality, public fields, copypasta everywhere – but a game nonetheless, and that’s what counts in the end. Then the fun started.
The game ran fine on desktop, Nexus 7 and Galaxy Nexus, but achieved only around 17 frames per second on my trusty Nexus One. It may be a few years old, but it’s not ancient, and Patchy’s graphics are really simple. I didn’t want to release something that was going to have crappy performance on all but the latest phones. What was going on?
Fortunately the Android SDK comes with really great profiling tools. Traceview doesn’t just show a call graph like a traditional profiler does; it also shows a timeline detailing the exact sequence of calls, and context changes between threads.
Running with profiling enabled dropped the framerate to about 12, but I thought nothing of it at the time. The output was surprising though: a lot of time was spent in updating camera matrices. Just a handful of floating point operations! (Okay, maybe in the hundreds.) Later this turned out to be an artifact of the profiler; instrumenting profilers add some overhead to each method call, and camera updates were performing a lot of tiny method calls for operations such as vector additions and dot products.
Having optimized away as many camera updates as I could (updating only if something changed), although it all but vanished from the profiling output, did not help the framerate one bit. The next biggest chunk of time was spent in text rendering. Building up the text character by character into a vertex buffer, taking care to use correct kerning and such, turned out to be fairly expensive. This, too, consisted of quite a lot of method calls and was – with hindsight – probably a profiling artifact. But fortunately, text is fairly static so I could use libgdx’s BitmapFontCache. This, too, had a big impact in the profiling data but didn’t change framerate one bit.
The next biggest chunk of time, around 18%, was spent on framebuffer operations. The cool, CRT-like retro rendering effect is achieved by first drawing the entire scene to an offscreen 240x360 framebuffer, then downscaling that twice by a factor of 2, then blending the three using linear filtering to achieve a blur/glow effect (and throwing in some scan lines afterwards). Now I found that, by commenting out this code and just rendering the scene to the screen, the Nexus One achieved a framerate of a steady 60 fps!
I tried to optimize, but nothing worked. Using just one downscaled framebuffer instead of two didn’t help. Using no downscaling at all didn’t help either. Various combinations of clearing and not clearing the framebuffer, as suggested here, didn’t help either. Without the profiler, I was just guessing what operations took long.
I could have instrumented the code by hand, but since it was still slow after ripping out almost everything that mattered, it seemed pointless. I concluded that framebuffer operations are just inherently slow on this device, and left it at that. Shipping, after all, is a feature.
This was the first app I’ve ever published to the Google Play Store, and I was pleasantly surprised by the process. Exporting a signed apk from Eclipse is really easy using the wizard, and uploading it to the Play Store is a breeze. Configuration of pricing and distribution countries/carriers is also really easy in the new Developer Console. I don’t know what the old one was like, but the huge yellow bar keeps nagging me that it’s going away soon, so I don’t suppose I need to care.
Most of releasing time was spent on creating promotional graphics. I drew the banner above in Gimp, mainly because I was too lazy to reboot to Photoshop. I’m not completely happy about it, but shipping is a really, really important feature, so once it had some colours and things in it, I called it done.
I chose to make it a paid app because this is the least hassle for me. I do realize that payment makes for a significant barrier to entry, even though the price is as low as I could set it (GBP 0.49, EUR 0.59, USD 0.99). My main objective with this project was not to get rich; it was to get some experience actually releasing something on Android, figure out how the process works, what to do and what to avoid. My next Android game will probably be a free one with in-game ads, and possibly in-game purchases.
Reception (or lack thereof)
I did no advertising or promotion at all, apart from posting to Twitter, Facebook and Google+. This led to a handful of friends buying it to try (thanks everyone!), but not much else. Patchy has been in the Play Store for a few days now, and I’ve seen only one or two purchases from outside my normally under-represented home country of the Netherlands.
Thinking about how the Play Store works, this isn’t too surprising: new apps don’t show up anywhere, except in search results. And nobody will be searching for “patchy” unless they already know about it. Some people might be searching for “arcade”, or “retro”, but I don’t think it’ll show up high for those generic terms either. I think the best chance for new paid games to “make it” is to end up in the “top new paid” category; the apps at the bottom of those typically have only 100-500 downloads. This doesn’t seem too hard to achieve, and would then drive early adopters and hopefully bump you to one of the other, more prominent categories. There used to be a section in (what was then called) the Android Market with new/updated apps, but with Android’s popularity these days, it probably became unwieldy. Pity.
But hey, it’s been only a few days since release. Patchy has received one review so far, it’s not from anyone I know, and it’s five stars out of five, so who knows… As far as I’m concerned, having launched is a success worth celebrating in itself!