Not the ‘droid I’m looking for

In my previous blog post, I talked about porting InterSceptre over to Android. I spent about 6 weeks on that project, but in the end I abandoned it and have started writing a new XNA game. I thought I’d write a quick blog explaining my reasons.

Reason 1: It’s just too hard!

Okay, honesty first. I thought porting to Android would be relatively easy. I’d need to write a simple lightweight implementation of the Microsoft XNA framework on top of the Android APIs – not too daunting since all I needed was sound, touch input, and 2D graphics. After that I could essentially copy and paste my source code, because Java and C# are syntactically quite similar.

Ha!

Actually to code porting wasn’t too bad. There are some differences in the syntax, yes, but more problematic was the way Java and C# differ in pass-by-reference/pass-by-value. Java is consistent: it’s always pass-by-reference. C# isn’t, and that way lies a world of pain if buried in the logic of your code you’ve assigned a variable expecting it to clone & copy the values rather than just give you another pointer to the same structure.

Other issues that fall into the “separated by a common syntax” bracket include:

  • Need an instance of an enumeration to get all values
  • Construction: base/super, call order of member variables vs constructor
  • Java doesn’t initialise “primitive” classes (e.g. Boolean, Integer, Float)
  • for/foreach syntax
  • unqualified case values in switch statements
  • lack of Properties
  • Differences in getting the size of collection classes – size/length/count
  • No operator overloading
  • Different GC strategies (Dispose())

These are all fixable, but are a right PITA. Slightly harder to deal with are the fundamental differences between Android and XNA:

Emulation. The Android emulators are unusably slow. Basically the emulator is a Java application that is emulating a hardware device (virtual machine), which is running the Android OS, and on top of that is running a Java application (your code). That’s several layers of emulation deep. I was getting 1 frame every 5 seconds. The only way to develop is with a hardware device, which even if you have one available can be awkward.

Screen sizes! Even relatively recent high-end Android devices have screen sizes smaller than the Windows Phone standard 800×480. This can be devastating if your games graphics are pre-rendered to fit that size. The biggest problem I’d have with InterSceptre would be fitting all of the options on the options screen, with the specially crafted text font I was using (note to self: use SpriteFont from now on). The in-game could adapt to smaller screen sizes, but I didn’t bother – in the end I settled for dynamically scaling the graphics so that the screen throught it was 800×480 but the rendering shrunk what was actually drawn.

But this really is symptomatic of a wider problem with Android – no standardisation. You can’t rely on anything. Sample Android game code that you’ll read on the ‘net is riddled with per-device exceptions and work-arounds. That’s insane, for a developer it’s a support nightmare having to keep releasing emergency per-device peculiarity patches for your games as they arise. Life’s too short to have to worry about that kind of nonsense.

Threading. Not hard, but you have to keep threading in mind in Android, lest your draw and update code clash over access to anything and you find yourself crashing out because of a ConcurrentModificationException. Very easy to do if, say, you’re adding to a list at the same time another thread is iterating through it.

Android alpha blending is XNA 3.1 style not XNA 4 style. In the move from 3.1 to 4, XNA changed from unmultiplied to premultipled colour values… or maybe the other way around, I could never get my head around it. Anyway, Android graphics still expect the old XNA 3 style colour values. So if like InterSceptre your game relies heavily on colourised special effects, you’re going to have to adapt an awful lot of code.

Vector maths. Android doesn’t have any. No, I couldn’t believe it either.

But the biggest issue for me by far was Canvas vs OpenGL 2D Graphics. The first 3 weeks I spent on the InterSceptre port, I was using simple Canvas.drawBitmap() calls to copy pieces of screen around. Once I’d fought my way through understanding the Paint and PorterDuff classes this worked fairly well; unfortunately InterSceptre performs a lot of screen copy operations per screen refresh, and as a result I was hitting the performance limits at about 10 frames per second – simply not fast enough for an action game like InterSceptre.

So, I ripped all the graphics code out (from my mock SpriteBatch class) and re-implemented it in OpenGL. This brought its very own challenges. There are no beginner’s guide to 2D OpenGL graphics tutorials anywhere, again you’re relying of scraping knowledge from someone else’s project. Noddy game samples all use Canvas of course, so if you need OpenGL you’re looking at a complex game such as Replica Island, and good luck understanding that if you have no idea how either Android or OpenGL actually work. OpenGL itself is a much lower level of coding than you use in XNA; it’s a set of arcane instructions to the graphics processor, and heaven help you if you can’t understand the gibberish you have to type in, or issue the commands in the wrong order. If something doesn’t work, you haven’t got a prayer of working out why.

OpenGL textures have to be exact powers of two wide and tall. No, I have no idea why this can’t be abstracted away from you. And there’s no easy way to change the size of a texture in memory before passing it over to OpenGL either, I had to resize all the graphics on disk, adding hugely and uselessly to my application size. Why?

But I persevered, asking lots of stupid questions on StackOverflow, and eventually got InterSceptre running in OpenGL. I had just 2 problems:

  1. I couldn’t use the same trick I did with Canvas, drawing everything fullsize to an offscreen 800×480 buffer then scaling that to the actual screen. OpenGL insists that offscreen buffers are no larger than the actual screen. This meant I had to draw each graphic scaled individually, and lost the nice antialisaing effect of just doing one big resize at the end. As a result, the game looked terrible – particularly the font, which suffered badly from artefacts
  2. It still wasn’t fast enough, I was only reaching 20 frames per second. On WP7 InterSceptre sits at 30fps with no problem at all.

Even then I probably would have continued, but when I couldn’t get sound effects and music to work either, despite following 2 separate examples that used 2 different sound APIs, I basically lost interest in Android completely. But while I’d been working on it, other issues had come to my attention that probably would have stopped me even if I was being successful:

Reason 2: Cheapskates.

Anecdotal evidence would seem to suggest that sales figures for independent games are just as bad on Android as they are on Windows Phone. There’s so much free stuff on Android that that’s what people expect, and so no-one wants to pay for anything, unless it’s from a big-name studio or franchise. So what exactly am I putting all this effort in for?

Reason 3: Long-term future of the platform

Android may be becoming the dominant mobile phone platform, but it is under threat from patent wars and the possibility of the Linux license being withdrawn. Google seems to have panic-bought Motorola to head off some of these issues. But things are so unstable at the moment, I’d rather steer clear!

Reason 4: Lack of Governance

The Android app market is riddled with malware as Google doesn’t seem to perform even basic checks about what an application is doing, unlike Microsoft (and Apple) who take a very close look. Will users continue to trust the platform, or will they defect to iPhone… or Windows Phone?

– – –

So… those are my reasons. I’m an XNA-only developer again, writing games for release on Windows Phone, XBox and Steam. It’s an exciting tiome to be a wp7dev and I’m looking forward to the ride!

Advertisements
  1. … and so the prodigal son returns home. Welcome back. 😀

    I’ve been keeping tabs on the Android situation myself – it’ll be interesting to see how other handset developers react now that Google is “playing favourites”

  1. June 14th, 2012
  2. January 7th, 2013

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: