Friday 5 February 2016

Releasing a game with Xamarin Android and Google Play (and... I'm back, again!)

It's been a year and a half since I updated my blog. The last update has me with a working prototype of my Inertia game (now 'Retro Rat Race').

During that time I have done a mixture of spare/part time game development (contract work for a business in the day times) then full time for a couple of months to get finished.

You can read my initial thoughts of Xamarin and my choice of OpenTK over Mono Framework in my previous blog post.

Just before Christmas I rounded off the first release of Retro Rat race (for Windows) and put it out there as shareware. The reception has been generally positive but it is even harder to get noticed than before. I reckon it's a good little game but just doesn't have enough of a hook to be noticed in a big way.




From watching videos that players have recorded (including the supremely helpful and enthusiastic YouTuber Seth Logan - @hayes1571), I can see the die/repeat pattern works well. It's certainly not an easy game but seems to elicit the appropriate "Arg, What, Arg, YES!" responses like the great games in the tough/short play genre such as Super Meat Boy.

It's funny with the Internet, in that I didn't know Seth until I started following him on Twitter and we established a rapport. He lives in Canada (about 3500 miles away) but somehow we've become friends and enjoyed some good banter on Twitter.

You can check out one of Seth's videos here: (if you don't mind a bit of friendly swearing!)


You can check out the Windows demo here: www.suisoft.co.uk/retroratrace/

After that I pressed on with finishing the Android version using Xamarin (Indie). That went pretty smoothly, despite a couple of hiccups with compatibility (almost resolved!)

The Android version lives here on Google Play.

Here are some hints/tips and experiences for those interested in game development.

Xamarin Game Development for Android

DO buy a good Android game development book

In order to learn about Android game development, touch controls, OpenGL ES, sound etc. it's really worth investing in a good book.

Beginning Android Games by Mario Zechner and Robert Green is excellent. It's in Java but Xamarin and OpenTK's clean wrapping of the Android API's makes conversion very easy.

DO consider 'Thunking'

Like the old days with 'DOS Extenders' allowing 32-bit applications to be used on 16-bit DOS, Xamarin Android passes control between the .NET virtual machine and the Java virtual machine. This obviously has some overhead (like passing between 32-bit and 16-bit).

This is most noticable, performance-wise when you are using Streams on top of Java objects. Every stream operation results in a 'thunk' between VM's. This caused me some trouble with map load performance, particularly on my Galaxy S3 phone. The fix is pretty simple for small files like game maps - just load it into memory then stream from there.

Don't try to create a batch build procedure with Xamarin Indie

I wasted the best part of a morning trying to get Xamarin's MSBuild to work following an example on their deployment documentation page. From what I can gather from scouring the Internet the build tools cannot be used directly with Xamarin Indie due to the licensing controls.

Instead, just use 'Project / Create Android Package...' from Xamarin studio and create a batch procedure you can run manually to sign & zip align from there. Signing and zip aligning steps are documented in the Xamarin guidance (link below).

Note that you can cancel the final dialogue box after 'Create Android Package' as the APK (Android package) files will already be in your BIN folder.

DO read the Xamarin deployment guidance

Xamarin's deployment guidance gives you a nice list of checks/tasks to perform. I recommend distilling these into a bulleted release procedure (as described below) to save time with future projects and releases.

Xamarin Deployment Guide

DO write a release procedure

This one applies to ANY software project.

I always write a release procedure when I build software with new tech. It saves so much time with future releases and projects. You won't miss things or keep thinking 'what did I do last time'.

You may need to split your procedure down into 'first release / major release' sections. The former includes the things you should only have to do once or occasionally after major changes. The latter is the tasks and checks you need to do every time, even if you're just releasing a patch (e.g. updating version numbers).

DO test with emulators as well

A trap I fell into with the first Android release, was an irksome bug where the keyboard didn't pop up, even if you pressed the 'text box' area on the screen.

I remember it took a fair bit of research and experimentation to get keyboard entry working, due to the game using its own user interface controls.

The functionality worked flawlessly on the physical devices I tested it on - several Samsung phones and tablets, a HP tablet (belong to a friend), a Kindle.

The issue was due to quirks in the behaviour of different flavours of Android. Specifically when calling 'ToggleSoftInput' I used the 'Implicit' flag, which worked fine on the test hardware. That flag needed to be 'Force' to work on some HTC/Nexus devices.

I could have avoided this problem by testing on a Nexus emulator. I'm actually still (at time of writing) looking into another problem for one player where the keyboard pops up and doesn't respond to key presses. I haven't pinned that one down yet - which brings me on to the next point...

Have a workaround in place for keyboard API issues

There are so many devices, tweaked versions of the Android operating system and custom keyboards out there, it's impossible (for a small Indie) to test everything effectively on real, physical hardware. I know Google and Xamarin have test cloud functionality but on initial reads, that seems more focused on Apps than games. If/when I explore that some more, I will post about it.

With a game, getting consistent keyboard behaviour appears to be a challenge (from recent experience!) To avoid this, make sure to remove the dependency on keyboard.

A mistake I made was requiring entry of a player name upon game start. If the keyboard doesn't pop up or can't be used it's 'game over'.

"That's it, man. Game over, man. Game over!"

I attacked this from two angles with a patch:
  • Skip the player entry entirely. Default to a 'Me' name that can be changed later
  • When entering the first player name, have a 'Skip' option that defaults to 'Me'
    (this handles the situation where a player has deleted the default profile)

DO test with other languages

Another compatibility issue I hit was a Portuguese (speaking) player who found the game crashed at the end of the first proper level. This was due to the medal time in the level being a float (e.g. 1.5) stored as a string in the XML level file.

When C# parsed it back to a float, it expected it to be Portuguese format (i.e. comma decimal place, rather than period/full stop). "SPLAT!"


I normally consider this angle with applications, as I've encountered it before. With my games written in C++ I haven't hit any localisation issues and missed it completely. Lesson learned!

C# and the .NET framework have localisation features built in. This is great, because dates, numbers etc. are shown properly. The Portuguese speaking player saw "1,5" (1 comma 5) on the medal screen. The downside, is if you persist something into a text file under one locality (i.e. English, Great Britain in my case when creating maps) and read it back in a different locality with different number formatting rules. "SPLAT!"


Google Play Store

DO consider the application naming convention

When I first uploaded my APK (android package) to Google Play it complained about the package name being invalid. It's talking about the package name in the manifest - NOT the name of the APK file (although I have adopted the same convention for that).

The package name is in the Android Manifest:

<manifest package="co.uk.suisoft.gamename"

To get a unique name, the convention is similar to your domain + the application name.

i.e. com.company.gamename
or co.uk.company.gamename
etc...

Don't worry about age classification

Before setting up my first application on Google Play I expected to be slowed (or blocked) by a requirement to assess the age rating of my game.

Google have actually made this very easy. Just a simple questionnaire that takes a few minutes to fill out. That becomes a set of classifications for various countries / regions.

DO consider the Goole Play Beta Testing functionality

You can pre-release to a closed set of beta testers. In an uncharacteristic moment of courage, I chose to 'Just go for it' (based on the current climate meaning slow uptake).

In retrospect I would have done a beta group, as per the Windows version of Retro Rat Race.

DO reply to reviews

The first three reviews I received for the game were negative - 1 and 2 stars. Some players immediately found the keyboard bug I hadn't picked up in testing. This was pretty gutting.

I replied to the reviews, apologising and informing the players I would look into it. Within a few hours I had a workaround for the problem allowing them to play the game. Two of the reviews were changed to 4 or 5 stars with a bonus couple of reviews praising the support.

Examples:
  • Respect for this developer - Ridiculously fast support update and the game is pretty awesome
  • Thanks for the quick fix to the keyboard problem
  • Good fun - Smooth game play and fun to play. Quick turnaround on the initial problem
I think gamers have become so accustomed to crap tech support. It's something special when you actually help them and give a damn. This is easier when you are small/solo/human without the bureaucracy of a corporation.

Summary

Overall, the process of getting a game onto both Windows and Android from the same C# codebase has been pretty smooth.

The game code doesn't contain a single line of platform specific code. The behaviour differences for devices are handled by a 'PlatformFeatures' class that I use to ask 'IsDesktop' to switch certain features on and off or adjust sizing / positioning.

The engine codebase is also mostly non-platform specific. There are specific subclasses for OpenGL, OpenGL ES and sound. Conditional compilation is used to keep them from bloating the other platforms.

Hopefully porting to iOS should be straightforward due to game code being 100% platform agnostic and the engine using the OpenTK OpenGL ES interfaces that should be compatible. The majority of the porting time will be the main game loop, storage and possibly sound (although I'm hoping my Windows OpenAL code may be OK).