Tuesday, January 21, 2014

How to have a full screen WHITE splash screen in Unity no matter the resolution

Note: replacing the Unity splash screen with your own is a Pro-only feature as of this writing.


The problem


If you develop mobile games with Unity Pro, you most likely want to replace the default Unity logo that gets displayed while the initial scene is being loaded with something more specific to your game or company. If your splash screen's background is black, no problem: the screen is cleared to black before the splash screen is rendered, therefore if your image does not fit the resolution of the phone or device displaying it, nobody will notice it. If you use a different color however, for example white, this is a different story, since Unity does not expose a parameter to change the splash screen's background color, as of version 4.3.3.


The options


Let's look at what the 3 options in Unity do. For that matter, I'll use a 768*1024 image created for the iPad, and try to make it work on a tablet with a 800*1280 screen resolution.

Option 1: "Center (only scale down)"


Since the image is smaller than the screen, it does not get scaled ("only scale down"). It is centered in the part of the screen that remains once the system bar at the bottom containing the back, home, and tasks buttons has been subtracted. When the game has finished loading and starts, it takes the whole screen minus the system bar, that is: not only the area covered by the splash screen but also the black bands around it, which looks odd.


Option 2: "Scale to fit (letter-boxed)"


This time, the image is scaled so that one of its dimensions (here: the width) fits the screen exactly ("scale to fit"), while the other dimension (the height) stays smaller or equal to the resolution. This means the splash screen is rendered as big as possible without being cut, and of course without using separate values to scale it horizontally and vertically. This is a bit better than before, since the vertical black bands to the left and right of the image have disappeared.


Option 3: "Scale to fill (cropped)"


Like with option 2, the image is scaled and its aspect ratio is preserved; this time however, the scaling ensures the splash screen completely covers the screen (minus the system bar), which in my example means its height perfectly matches the screen, but parts of the image are cropped on the left and right. This actually does not look bad here, because I got lucky; with other resolutions though, I cannot guarantee part of the pots, or the logo in the bottom right corner, or even the game name, will not get cropped, which would look terrible (you can see it's already very close, with the shadow of the rightmost pot, or the last letter of the game title).


The solution


Now that we've seen our options, let's go back to what we want, or actually what we don't want: we certainly don't want black bands around the image if it's smaller than the screen resolution (option 1), and we don't want parts of the image to get cropped (option 3). Option 2 seems to be the best one, except for the splash screen not being tall enough to avoid letter-boxing. Well, let's make it much taller then! Since I'm not aware of any mobile device with an aspect ratio greater than 2:1, I chose this value and extended my splash screen to make it twice as high as it is large (768*1536):


Now, using option 2 would not work anymore: since the image is so tall, "scale to fit" would mean its height fits the screen, and letter-boxing happens on the left and right. Option 3, however, now ensures the image width matches the screen's resolution, and some of the white I added at the top and bottom of the splash screen gets cropped. Can part of the initial image also get cropped? I don't think so, since it was 768*1024, and no device should have a landscape ratio under 4/3 (it would pretty much need to have a screen shaped like a square).

This is what the result looks like:


Monday, December 16, 2013

A few tips for Unity I learned while porting Flower Garden (2/2)

Editor related


Unity defines some symbols that you can use in your scripts, for example to have slightly different code on different platforms, or to run some code only inside or outside of the editor, like this:

#if UNITY_EDITOR
            language = "French";  // TESTING
#else
            language = UnityEngine.Application.systemLanguage.ToString();
#endif       


At some point, you're probably going to need to define your own symbols, which you can do in the Player Settings, under Other Settings | Configuration | Scripting Define Symbols.


The important thing to remember is: when you modify these defines, you must validate your changes by pressing the Enter key; you should then see a little rotating progress circle in the bottom right corner of Unity's window, that indicates the scripts are being recompiled with the updated defines. If you don't press Enter, your changes won't get saved, and they won't have any effect when you re-run your game.


If you write a script that requires the object it will be attached to to have some specific components, you can declare it like this:

[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class TurtleUITexts : MonoBehaviour

When you drag and drop the script to apply it to an object, the specified components will automatically be added by the editor if they're not already present. However, keep in mind that if the script is already attached to some objects when you add the RequireComponent attribute, those objects will not get modified, this process only happens when the script gets attached.


A nice feature I only discovered recently is the "size and ratio" drop down menu of the Game view. It allows you to see what your game looks like at some specific resolutions, and you can add your own to the predefined ones. If you're working on mobile, you will get both portrait and landscape options. I find 480*800 (WVGA) works very well with my window layout, I just have to make the game view slightly bigger than that to minimize the borders, and I'm all set.



I usually work on a PC desktop, but after a while I wanted to show Noel where I was at, so, I copied the Unity project to my laptop, made a Mac standalone build, ran it for a few seconds to make sure it launched OK, and sent it. When I got some feedback, I was very surprised to read everything was good, except for the textures looking low res. I checked on my laptop, and indeed the game wasn't looking as good as on the desktop, although the code and assets were exactly the same. If this happens to you, here is where you should go first: Edit | Project Settings | Quality. 


On the above screenshot, you can see that texture resolution is divided by 2 for the Fastest quality setting (selected at the top), that was my problem (either it was the default for Mac standalone when I built, or my laptop sucks). You can also notice shadows are completely disabled for that setting, there is no per pixel lighting (Pixel Light Count = 0), etc. When you select a line in the quality Levels matrix (at the top), the Game view will reflect these settings immediately, which is great.


The other day I was having some trouble setting the dimensions of a standalone PC app, I wanted my window to be 480*800 like on a WVGA phone, but somehow the app kept reusing some values I had used previously (I think I submitted a bug about that a while back). Anyway, since I couldn't get it to work from the player settings, I decided to hack the values wherever they were saved. Problem is: where does Unity save them? On Windows 7 at least, it's not in a text configuration file under some c:\Users\myUserName\ folder like I was expecting it, those settings are stored into the Windows registry. Or maybe I should say "the dreadful registry", since I personally hate this thing. Anyway, there it is: if you need to edit those settings, or nuke them, on Windows, regedit is your guy.


Testing and debugging


Debug.Log (in the UnityEngine namespace) is your friend. If you're working on a fairly big project and not using it, I don't know how you're doing it, especially on mobile. When playing the game in the editor, messages go to the console window, when playing on a phone they go to its logs (see "Android" section below to read the logs on Android). If you plan on removing all the messages before you publish your game, simply put your calls to Debug.Log inside a define, that you enable or disable from the player settings.

#if DEBUG_INFO
            UnityEngine.Debug.Log("unsupported language => fall back to English");
#endif


This is not specific to Unity, but one thing I find useful when the game is being tested by volunteers is to have the build/version number displayed in a corner of every screen, so that it will be visible on screenshots. At some point I was pushing a new build each day with the latest fixes, it was quite unlikely everybody was always up to date, and when you get a report saying a problem is still happening, you certainly need to know what version was being run.


In the same spirit, I would recommend not silently swallowing (catching and not re-throwing) too many exceptions during development and testing, even if you're going to do it in the end. For example, obviously I don't want the game to crash if it cannot find a save game file for some reason, but I definitely want to know about it if that's not supposed to ever happen. In this case, Debug.Log won't cut it: it's fine if I'm the one testing and I'm looking at the logs, but other testers won't see the messages.

You could use a library for analytics to send them to a server (which I actually do in Flower Garden when an exception is caught), but that won't give you much context. For a tricky bug I had to fix but could not reproduce myself, my solution was to hack a message dialog class already in the game, and display some information as soon as I could detect the problem; this way, in addition to the call stack, I also got some details from the tester in Slovenia regarding what she did just before the dialog showed up. In future projects, I think I'll reuse this method and generalize it.



Android


If you're developing on Android, you should be familiar with adb (the Android Debug Bridge). It's a program you run in a console (on PC) or terminal (on Mac) window to communicate with your Android device. It can do a bunch of things (for example: push or pull files from/to your computer), but mostly you want to use it to monitor the logs your game spits out while running. This includes the messages you print from your scripts with Debug.Log, but also some messages from Unity itself, the plug-ins you may be using, etc. adb is located under the sdk/platform-tools folder of the Android SDK, and here are the most useful commands:

see messages coming from Unity: adb logcat -s Unity
clear the logs: adb logcat -c


If for some reason you wanted to run your Android game in the emulator, maybe to see what it looks like in a different resolution than the ones of your devices, or with another version of the Android OS, I believe you're out of luck. The first problem is: the ARM emulator that comes with the SDK is still as slow as when I used it in 2011, and I doubt you'll be able to stand the pain for long. There are a few alternatives, I tried the x86 one from Intel, I was indeed able to run my old native game Jigsaw Guru on it, and the performance is pretty decent. However, you cannot use it for Unity projects, apparently because the engine's compiled libraries are only available in ARM format.
(see Unity\Editor\Data\PlaybackEngines\androidplayer\libs)


Sometimes you may need to look at your program's manifest, usually to check all the permissions your project requires are included. This is easy: build the apk from Unity, then open AndroidManifest.xml under the Temp/StagingArea folder.


Windows Phone


I just started using the Windows Phone add-on, and initially I got what looked like immediate crashes after the splash screen when using "Build and Run" in Unity, and with "Build" Visual Studio would crash trying to open the solution generated by Unity. To fix all of the above, I just had to make sure I was on the latest everything: I installed some Windows updates, replaced Unity 4.2.2 with 4.3.1, and got the Visual Studio 2012 update 4 - I think the latter was actually the missing piece. After that, no problem, everything works as advertised, great :)


I'm still using MonoDevelop for now to write scripts, and I always compile them there to fix errors before switching back to Unity. The C# projects generated by Unity are configured to use .NET 3.5 by default, which is not installed on Windows 8. In MonoDevelop, you can change their settings to use .NET 4.0 instead, but this will get overwritten each time the projects get recreated. So, do yourself a favor, and install .NET 3.5, it's straightforward and quick.


This is not specific to Unity, but if you haven't done any Windows Phone development before, you probably don't know the .NET version used on this platform doesn't implement all the namespaces and classes you're used to. I forgot about it too, and the Flower Garden code base for Android required a few changes to run on WP8. For example, XmlDocument and its associated classes (XmlNode, XmlAttribute) isn't there to load and parse xml files, you need to use XDocument / XElement / XAttribute instead.

File.WriteAllBytes(somePath, byteArray) isn't supported, you have to do something like this:

using (var stream = File.Open(somePath, FileMode.Create))
{
    using (BinaryWriter writer = new BinaryWriter(stream))
    {
              writer.Write(byteArray);
    }
}


Mecanim


This is not related to Flower Garden, but I tried Mecanim recently, and here are a couple of things that gave me trouble. Once you know about them, things become easier.

I started with the robot character from this Mecanim tutorial, and tried to add a run animation to it. No dice, until I changed the type of the animation to 'humanoid', under the Rig tab of its import settings. Obviously that makes sense, for the robot has that type as well, but since I was attempting to apply the animation to the robot, you would think Mecanim would figure out the types needed to match, or at least give me an error about it in the console.

Then I wanted my animation to loop. When selecting the corresponding state in the Animator window, you see a few parameters for the animation, such as its replay speed:


But where is the "loop" checkbox? It turns out looping or not needs to be decided when importing the animation, as shown below. Whether that is intuitive and convenient or not to have this setting here is another story.



Monday, December 9, 2013

A few tips for Unity I learned while porting Flower Garden (1/2)

Using two versions (or more) of Unity on your computer


By default, when you install a new version of Unity, it replaces the current one. But it is actually possible to keep more than one version on your computer, which is useful if you're working on a project and don't want to upgrade immediately, while still being able to try and test the latest features. For example, when I was finishing to port Flower Garden to Android, and getting ready to publish it, I kept using 4.1.2 since it was stable and the next versions introduced some bugs I could not work around; but at the same time I was also getting those versions, to check if there were some improvements the game could benefit from in the future, and verify what the status was on those aforementioned bugs.

Keeping several versions is not difficult: before installing a new one, you just have to rename the folder containing the current one, et voila. For example, on Windows 7, I have the older version in c:\Program Files (x86)\Unity4.1.2, and the newer one in c:\Program Files (x86)\Unity. To run the current version, I use the usual Unity icon; to launch the old one, I suppose I could create another icon, but I got into the habit of opening a command window, navigating to the desired folder, and launching Editor\Unity.exe.

By default, Unity reloads the last project you worked on; but if that was a 4.1.2 project, and you're launching 4.3, you don't want this behavior since your project would be converted to 4.3 and you may not be able to load it in 4.1.2 anymore. Fortunately, Unity warns you about it. One solution is to specify what project you want to open, like this:

Editor\Unity.exe -projectPath myProject

Or, you can also use a project name that does not exist, and Unity will bring up the Project Wizard dialog. However, the easiest way to solve the issue is to go to Edit\Preferences\General in Unity's menu, and check Always Show Project Wizard once and for all.


When you go back and forth between versions of Unity and projects like this, it is possible that after loading your scene looks empty and your hierarchy tab only contains the Main Camera; do not panic, somehow the scene selection got lost, and you just have to find and double click your scene in the Project tab to bring everything back to normal.


Version control


As soon as you start working on a project, you should put it under version control, so that you can go back in time and check the changes you made even weeks ago if something goes wrong, or merge with other people's changes if you're part of a team. In its initial configuration, Unity is very unfriendly with external version control systems (by "external" I mean: anything other than the Unity Asset Server, which is a separate paid product): it creates lots of binary files in the Library folder, mostly under Library\metadata, and there is no way to know which ones need to be checked in. Even if there was, that wouldn't be very useful, since binary files cannot be merged, and looking at differences tells you nothing.

Fortunately, some version of Unity introduced a setting that will make your life easier: go to Edit\Project Settings\Editor, and in the inspector, under Version Control, select the Visible Meta Files mode. Ideally you should do that before you create anything in your project, otherwise you probably want to quit Unity so that the magic happens. Basically, once you're in this mode, every file under the Assets folder will generate a new file of the same name with an additional ".meta" extension, that contains some information about the corresponding asset. For example, the values of the parameters you can edit in the inspector for one of your textures. These meta files are text files, therefore it becomes possible to diff and merge them.


This is great for most assets, but it's not a silver bullet: scenes and prefabs are still stored in binary files, and cannot be merged if two people modify them around the same time. For more information, see the following links:


Scripting and rendering


If you load resources with Resources.Load, you need to know it doesn't like backslashes in its file path, only forward slashes should be used. This is especially annoying on Windows, where backslash is the character used by Path.Combine to concatenate strings. Therefore, don't forget to do something like: string filename = Path.Combine(ContentRoot, name).Replace("\\", "/");

Since the geometry in Flower Garden is procedurally generated, and although it could still have been stored in game objects, I didn't feel the need to use mesh renderers and mesh filters: instead, I call the lower level Graphics.DrawMeshNow function, that takes a mesh and a matrix. Since I was taking that path, I thought I could do all the processing and rendering of a single frame from the Update function of my main script, pretty much the same way it works in the iOS version. That's not the case though: rendering doesn't work in Update, because the camera hasn't been set up yet and the frame buffer cleared, etc. OnRenderObject was the right place for me, OnRenderImage and OnPostRender are also worth checking out if you're thinking of doing some "manual rendering".

At some point, I wanted to apply a specific change to all the textures in my project, and I thought: Unity sure knows who they are, and has all the code needed to load them, so why not write a C# script, attach it to the main camera, and launch the game in the editor once to run the code I'll put in the Start function? That sounded clever, until I realized most of my textures were compressed and read only (most of yours probably are too), and I needed them uncompressed and writeable in order to process them. No problem, a quick search in the forums told me how to retrieve the corresponding texture importers, and change their properties before loading the textures the way I wanted them. Problem is: when you do that, you don't work on copies of the importers, you really modify "the real thing", and after happily running the game, you soon notice you lost all your texture compression settings. So: be careful, and use version control so that you can revert those unwanted changes.

Shaders in Unity are a strange beast, at least at first. I've written simple shaders before, in assembly and HLSL, but when I started looking for examples to do it in Unity, it seemed like there were 3 different ways to do it, which I found confusing. My understanding is: you can use commands to rely on color combiners and the fixed function pipeline, or write Cg code, or use some kind of meta programming that will allow your shader to work correctly with Unity's lights in both rendering modes (forward and deferred). Anyway, the thing I want to point out is a bunch of rendering states (for example: writing to the z-buffer or not, changing its test mode, setting the blending mode, back-face culling, etc) are hard coded in the shader, and I did not find a way to turn them into parameters I could set from script. I can see why it was done like this, but it means each time I want to reuse a shader with one or more rendering states having a different value than before, I need to duplicate the shader. Not a huge deal in my case, but that's how Flower Garden ends up having 23 shaders (which I'm sure you would not guess by looking at it).

When assigning data to a Mesh, it seemed using null was not a good idea (I haven't verified it recently, this may have changed). For example, if your data doesn't contain texture coordinates, don't do mesh.uv = null; (that would trigger an error), just leave that array alone. Same thing for normals, etc. I can only assume mesh.uv (in my example) references a zero-sized array by default, and replacing it with null prevents the engine from getting its length, or something like that.


Making builds


Creating builds may fail on some platforms if some of your files are read only (for example, if you're using Perforce for version control, and haven't checked those files out). The one I know of from the top of my head is AndroidManifest.xml, that gets copied to Temp\StagingArea during the build and needs to be writable to get modified.

Code stripping is not as smart as you may think. This Pro-only feature, found in the Player Settings under Optimization | Stripping Level (for some platforms only), is meant to reduce the size of your executable (and therefore the size of the file people will download to play your game) by removing some libraries your script code is not using. Ideally, this would mean that after the compiler has done its job, the build process would figure out what classes or dll's are required, and get rid of the rest (which is pretty much was this page says:
http://docs.unity3d.com/Documentation/Manual/iphone-playerSizeOptimization.html).

In reality, at least on Android, this is not what happens: it looks like a predefined list of classes, that are supposed to not be used very often by most developers, is simply excluded from the build, without any further test. I believe encryption classes are part of this list, and HttpWebRequest most definitely is: when I tried to enable code stripping in Flower Garden, the game would crash as soon as a script tried to use this class, that could not be found anymore (and no, I am not accessing it through reflection). One problem is: I don't use that class a lot, therefore I did not notice the crashes immediately, and when I got one it took me a while to realize code stripping was the culprit. No compiler error, no error when building, it's nasty. When I finally understood the issue, I had 2 options: disable code stripping, or rewrite the scripts that used the missing class in a different way; since I was getting close to publishing the game, and had 100 other little things left to do, you can guess which solution won.

Since then, I learned there is a third option: you can create a link.xml file under the Assets folder, and specify in it some namespaces that should be included in (or: not excluded from) the build. I haven't tried it yet, which is why I'm borrowing the encryption example I found (warning: use at your own risk), instead of following up with HttpWebRequest. It's good to have this workaround, but it still looks to me like I'm doing the job of the computer, that should be able to figure these things out much better than me.

<linker>
 <assembly fullname="mscorlib">
 <namespace fullname="System.Security.Cryptography" preserve="all"/>
 <namespace fullname="System.Security.Cryptography.X509Certificates" preserve="all"/>
 </assembly>
</linker>



To Be Continued...

Monday, December 2, 2013

Time flies

I recently noticed my last post on this blog was over 2 years old; seriously? Maybe it's time to catch up then, before I try blogging about some topics I've been interested in lately.


Full time job 


This is one lame excuse for stopping to write in 2011: after publishing my second game on Windows Phone 7 and Xbox Live Indie Games, I had to take a full time job and go back to working in an office rather than my apartment. I actually joined some of my former colleagues from High Moon Studios at Zynga San Diego, where I wrote server and client code for the web versions of Cafe World, Bubble Safari, Bubble Safari Ocean, and Ninja Kingdom.


I learned a lot in the process since I didn't know anything about Facebook games, PHP (on the server side) or ActionScript (on the client side) when I started, and I got to see what it's like to run a live game that reached 7M daily active users around June 2012 (Bubble Safari), and update it several times a week to keep the players happy and busy. I also got to renew my collection of free mugs and free shirts, but that's another story ;)


Personal projects


I had bought a MacBook Pro a couple of weeks before I started at Zynga, and although the new job was keeping me plenty busy, I began porting my game Jigsaw Guru to iOS in my spare time. The idea was to learn the platform and some Objective C, I wasn't planning on making any money with this project since there are tons of jigsaw puzzle games on the iPhone. This turned out to be even more true than I could imagine: despite getting more downloads than I expected (nothing spectacular though, about 14k), I haven't seen a single cent because I went with Mobclix for in-game ads, and they simply stopped paying developers around the time I published on the AppStore. Fortunately I'm not losing much, but still; I've never had any problem with Microsoft's PubCenter on Windows Phone 7, or Smaato on Android, but I would obviously recommend avoiding Mobclix and Velti (the company that bought them) like the plague.

Since I talked about downloads, here is a strange fact: when I published Jigsaw Guru on iOS, and although it didn't make much noise at all, I saw a significant bump in the number of installs... on Android! It cannot be a coincidence, the two dates match exactly. This makes no sense to me, I don't know how these people suddenly saw a game that had been on Google Play for 20 months already, it's a mystery. Oh well.


Porting Jigsaw Guru took me a bit more than a year, since there were a few periods when I was not touching it for weeks. I also spent some time playing with a free trial of Unity Pro, and once Jigsaw Guru got out of the way, I started converting Flower Garden to C#.


Flower Garden


Flower Garden is an iOS game that, even if you never saw it at the top of the most important charts, has had a lot of success since it was created and published on the Appstore in 2009 by my friend Noel Llopis. It had not been ported to any other platform yet, and after verifying Unity should ease the pain of developing on Android, I decided to tackle that challenge. There was a lot of work to be done: the code base is about 3 times bigger than Jigsaw Guru's, understanding somebody else's code is slower, I had to replace UIKit with something else, make sure everything on screen would scale properly on the many different resolutions available on Android, and of course performance and stability have to be solid. As porting Jigsaw Guru already took over a year, this would have been an endless spare time project; but since I wanted to try being indie again at some point, after a few months I took a risk and quit my job to work on it full time.

Development took more time than I estimated (I know: what a surprise!), and I learned a bunch of things once again. For example, this is the first time I use in-app purchases, which definitely require a bit more code (for the shop) than ads. The game was published worldwide on Google Play at the end of October, and a few days later on Amazon. So far, it hasn't been doing too well: it's completely invisible in the store, very hard to find even knowing its exact name (!), and therefore downloads are increasing very slowly in both stores. Ratings are good though, so, hopefully Noel and I can figure something out, or get lucky.


Anyway, that's all I wanted to cover this time, and as you can guess there is a good chance I'll talk about Unity and Android development (with Unity) in my next posts.

Sunday, July 17, 2011

Postmortem: Ace of Dynamites

After the bad experience I had developing on Android (and equally poor commercial results: with about 300-350 new or updated apps in the puzzle category alone, less than 48 hours after I released Jigsaw Guru, my game got buried in the depths of the marketplace immediately, and it made about $5 of ad revenue in the first 3 months), it was time to go back to my beloved C# and XNA, and make another game for the Windows Phone 7 (WP7 for short), and XBox Live Indie Games channel (XBLIG). This time, I didn't completely start from scratch though: I decided to remake a game I initially created on the Amstrad CPC 6128 twenty years ago, when I was a student with some spare time on his hands.


The project

The original game was brutal: because I was using some hardware trick to scroll the screen at 50 fps, I couldn't do it by less than 4 pixels at a time, which means every move was extremely fast (since, in mode 0, the resolution was only 160x200. For those who are interested, I was also using an overscan technique to cover the whole monitor, and another CRTC reprogramming to have an area at the bottom of the screen that wasn't scrolling, and used the more detailed mode 1 to display times and high scores). Of course nowadays you just redraw the screen each frame and make your level scroll at the speed you want, and I certainly slowed it down a lot in the new version, but the principle of the game hasn't changed: you control a character in 2D tile-based levels, there are enemies bothering you on your way to the exit, and you can push crates and boxes full of dynamite sticks to block or blow these enemies up. I don't have a screenshot of the CPC game (and I haven't actually been able to play it in many years, as the computer's drive belt is dead and needs to be replaced), but here is one of the PC prototype I made with the exact same graphics (hence the low resolution blockiness), next to what is now level 3.1:

The CPC game was called Dedalis (dédale being another word in French to say maze), but I changed the title to try to find something that would describe a bit better what the gameplay is about. Also, unlike in Ace of Dynamites, there was no gem to collect, and no award to unlock, but the rest is pretty much the same, especially the different tiles and what they do.


What went right

Working on a game I already knew and played, even years ago, definitely had some advantages. Of course I had to make many adjustments because of the different platforms, input systems, audiences, etc; but since I'm currently thinking about my next project idea, and trying to figure out what is going to be in it, how it's going to look, and how the different elements will fit together, it's easy to see I have a lot more question marks this time than I did when I started Ace of Dynamites. I wish I could play my next game before starting to work on it, and have a better idea of where I'm going with it; that's basically what happened here.

Developing the WP7 and XBLIG versions at the same time was also a good thing. When I created Jigsaw Guru, I made the WP7 version first, then an Xbox360 version, and finally ported it to Android. The problem with that is each platform has its own characteristics , in terms of performance and resolution for example, but also regarding what you need to provide when you submit the game. Reworking the UI of Jigsaw Guru to make it match completely different aspect ratios took a few days; needing an extra logo to publish a free version wasn't something I had planned for; discovering the 3rd platform required a thumbnail in a much higher resolution than the ones I had wasn't a nice surprise. So, being able to cover all the bases from the beginning, and verify I wasn't putting myself in a corner at any time in the gameplay or UI departments, was definitely a plus on Ace of Dynamites. And if I ever wanted to do an Android version (not that I'm thinking about it at all!), I made sure I have all the iconography I would need.

This one is going to sound like a joke, but it's true: having a phone to test the game was great! As I explained in the postmortem of Jigsaw Guru, I developed my first WP7 game entirely in the emulator, since that was before the phones went on sale. I said the emulator was very reliable, but still: only real hardware can give you a good idea of the performance, it's reassuring to see the game run correctly on one of the devices people will use to play it, and more importantly the emulator can't replace the touch screen when it comes to deciding if some elements have the right size and are not too close to each other to be tapped. Go back to the previous screenshots: on the right one, it's obvious I moved the camera closer, this has the drawback of showing a smaller portion of the level, but without this change I found it was very difficult to tap the exact tile where you want your character to go. In the emulator, you almost have pixel perfect precision all the time with the mouse, and your finger doesn't get in the way, this is a big difference.

Pretty early in the project, I decided I would submit an Xbox360 build of Ace of Dynamites to the Dream Build Play (DBP) competition. That gave me a deadline to shoot for, without adding too much pressure since the game didn't necessarily have to be finished. Of course I wanted to put as much polish as possible into that build, and I think that helped me staying focused.

Working with the same artist as for Jigsaw Guru was a big plus. I knew what Aimee could do, and that we would hit the ground running instantly since we knew what to expect from each other, and even if she wasn't available immediately when I contacted her, I waited rather than look for somebody else. That meant she had less time to do all the art than I had initially planned to give her, but she managed to finish everything a couple of days early nonetheless, which was great. And maybe I also learned my lesson from the previous project: this time the list of what I needed was already finalized before Aimee started to work, I made sure all the question marks had been removed.

Finally, I spent more time polishing this game, and adding little details here and there. For example, when a menu command is selected, in addition to changing color, the dynamite stick that represents the command (Aimee's idea) also generates sparks like if the wick was burning, which emphasizes what item is selected even more, and makes the screen look a bit less static. This is a direct consequence of not having a hard deadline to submit the game, unlike on Jigsaw Guru when I was trying to have a launch title.

Guess what command is selected? (Xbox360 version)


What went wrong

I believed I would be able to reuse most levels from the original CPC game; what a mistake! It actually didn't work that way for several reasons: some levels were too big, especially now that the character moves slower; some levels were too long to complete, in particular for a phone game where play sessions can be quite short; some levels relied on a couple of tiles I didn't keep in the remake, because what they did was a bit confusing; and finally, some levels were just too hardcore. I was still able to use a few maps as is, but in many cases I had to make modifications, or build something different based on the same idea or puzzle. And I had to create and test a bunch of brand new levels, those are usually the ones that are smaller.

On the CPC, handling the character movement and collisions was simple: because one step of the hardware scrolling was exactly half the size of a tile, the character was always either not on a tile at all, half on that tile, or exactly on the tile, on each axis of the 2D world. This is not the case anymore, I implemented real 2D collisions in Ace of Dynamites, but I had a lot of problems with the arrow tiles. As soon as you overlap one of those, even by a very small amount, it's going to start pulling you in the direction pointed by the arrow. In some levels where arrow tiles are next to each other and form some sort of treadmill, that has turns and corners, it was very easy for the character to not take the turns perfectly and end up bumping into some static skull and die. You can imagine how frustrated the testers were.

On the WP7, it's a bit like I have 3 versions: the free game, the paid game when you're playing it in trial mode, and the paid game once you bought it. I didn't think that would be much of a problem, but actually it was. The deal is: the free game has 10 levels, the paid game has 20, but in trial mode you can only play the first 10 (so that it's equivalent to the free game), and at some point I'll add some bonus levels to all versions. So, the question was: for each version, what happens when the player completes the 10th level? The answer is: in the free game, the player goes back to level 1 and the difficulty mode increases, unless there are some bonus levels in which case the player goes to the first of them and the difficulty stays the same; in the paid game, the player goes to level 11 and so on, and after 20 is when he either loops back to level 1, or starts the bonus maps; in trial mode, the game jumps from level 10 to the 1st bonus (which is basically level 21) since levels 11 to 20 are not accessible, or to level 1 if there is no bonus yet. Yeah, that's quite a mess indeed, having just one single case would sound easier, but I wanted to give another shot at having both paid and free versions of the same game in the marketplace, since I didn't do it right with Jigsaw Guru (the free game was an afterthought, a different experiment, that wasn't even advertising its paid counterpart).

The end of this project wasn't fun. After I entered it into the DBP competition, and finished the last few tasks related to polishing the game, all that was left on the XBox360 was submission related (trial mode, a few bugs, the evil checklist...). Then I needed to deal with a bunch of WP7 specific tasks, since I had focused on the console version for a while because of DBP, and those were not exciting either: a few bugs only happening on the phone, certification requirements, trial mode, adding ads, tombstoning, that sort of things. I was hoping to be done at the very end of June, but as often in software development it took a bit more time, and what I'm going to talk about in the next paragraph played a part in that too.

I don't use much middleware really, only the EasyStorage library because it makes life easier to handle saved games on the Xbox360. But this time I wanted to have online leaderboards in the WP7 version, and also try adding analytics, without implementing those things myself. Since I knew some free and battle tested solutions existed, my mistake was to think integrating them would be a piece of cake, and to do those tasks last. Integrating Preemptive Solutions' analytics was in fact easy, but somehow none of my data was showing up on their website, except for the name of my game that was there to prove some messages had indeed been received. When statistics finally appeared 4 days later, I saw they didn't give me the information I wanted, made some modifications, played the game again to generate new data, saw it was queued on the website... and one week later, it still hasn't been processed. I don't know what's up with that, I was certainly hoping for something much closer to real time information, but this is my experience so far. For the leaderboards, I chose Mogade, and it was only a question of bad timing: the code just got rewritten, I ran into a few bugs, and I spent some time verifying my code wasn't the culprit, and looking for workarounds. Fortunately Karl, the author, was very responsive, and fixed the issues very quickly. But the lesson is: when you integrate some external library you haven't seen before, don't wait until the last minute, even if it seems like it's something trivial to use. That's basically why I'm not using the latest version of the Microsoft ads SDK yet: it was released very recently, I was reading in the forums some people had trouble using it, and I didn't want to postpone my submission just to figure out what changed; I'll look into it when I'll make an update for the game.

Monday, May 30, 2011

The Android experiment: porting my XNA game to Google's platform

In this post, I'm going to talk about my experience porting my XNA game Jigsaw Guru Free from the Windows Phone 7 platform to Android. I will focus on the development side of things only, marketing a game on Android and the fact that there are multiple market places (including the quite recent Amazon Appstore for Android) would be a totally different topic.


Why?


Why try a new platform?

Once I released Jigsaw Guru on WP7 at the end of October 2010, I started working on an update, and prototyping a couple of other ideas. When the first sale numbers became available in December, and I saw how low they were, I stopped what I was doing and spent a few days making Jigsaw Guru Free, a free ad-supported version that got published just before the New Year. And I finished the Xbox Live Indie Game version of the program.

Then what? I could have worked on another WP7 game immediately, but the initial results from the ads were neither bad nor very encouraging, until I changed my ad categories and eCPM went up a few weeks later. Since I already had a full game implemented, with all the necessary assets (that I didn't make myself, since my artistic skills are extremely limited), another option was to port that game to a different platform, with a larger user base.

Why Android?

I basically had to choose between Android and the iPhone. Since I don't own a Mac (I know there are a few ways to develop on iOS without one, but ultimately if you want to have access to all the libraries and not be limited to some specific middleware SDK, I think you need one), I decided to try the Android tools for Windows. Android is supposed to be the fastest growing mobile market these days, and lots of tablets are going to be sold this year, so why not?

Why Java?

On Android, you can write code either in Java, or in native C/C++. On one hand I have many years of C++ experience, on the other hand I only read a book about Java a few years ago to see what the syntax looked like, so why did I choose to use Java? One reason was learning a new language can be fun :). Another one is C# and Java both have garbage collection, and therefore Java was a better match for the code of Jigsaw Guru, that doesn't care about deleting objects manually all the time. I would have used C++ if there had been a good reason for that, but what are the reasons to use native code on Android?
  • reusing an existing C/C++ code base. Well, Jigsaw Guru is written in C#.
  • performance. My game sometimes has to draw a bunch of stuff, but on the CPU side there's not much happening, I thought Java would be fine.
  • access to OpenGL ES 2.0. Yes, on Android you can only use GL 1.0 and 1.1 from Java, if you want to call 2.0 you have to do it from native code. But since I only used 2 different shaders from XNA (BasicEffect and DualTextureEffect), it was no big deal emulating them with the fixed function pipeline.
So, in the end, I didn't have any good reason to use native code, and reading the online documentation gave me the impression installing the native SDK (called NDK) on top of the rest was not super fun, and that debugging native code was not well integrated into Eclipse (the development environment).

Why not MonoDroid?

When I started developing on Android, MonoDroid (an SDK for running C# code on Android) was not ready yet. Even if it had been, I don't think it would be that useful for a program like Jigsaw Guru: sure, it would take care of running the C# logic of the game, but it wouldn't auto-magically remap the WP7 input, sound, file system, and rendering to the Android platform (and I'm not even talking about tombstoning, or the WP7 Chooser Tasks). For that, you would need something like ExEn, which wasn't ready for primetime either.


Installation


The installation process can't be easier for the WP7 tools: one executable, and you get Visual Studio Express 2010 if you don't already have it, XNA 4.0 (which also allows you to develop on Windows and Xbox360), the WP7 emulator, etc. It takes a while, but you can go do something else in the meantime.

For Android, there are a few more steps, since I had to install: the Java Development Kit (JDK), Eclipse, the Android SDK, the components for the versions of Android I wanted to be able to use (for example: 2.1 + 2.2 + 2.3, and now 3.0), and ADT (the Android Development Tools, which are basically a plug-in for Eclipse). Overall it went quite well, the only problem I had was with the JDK: there are 32 bit and 64 bit flavors, guess which one I picked since I run Windows7 64 bits; but apparently some of the tools are hard coded to use the 32 bit version, and I had to install that one in the end or nothing would work.


Eclipse versus Visual Studio


I've been using Visual Studio for a very long time now, since version 4.2 I believe. It's a very good code editor in my opinion, and probably the best debugger used in video game development. So, how does Eclipse (which is free) compare to Visual Studio Express 2010 (also free)? Let's start with the things I definitely liked:

  • the suggestion window. If there is an error in the code, and you put the mouse cursor on it, a floating window shows up with suggestions on how to fix the problem. Here is an example, where I started declaring a local variable "m" of an unknown type "Matrix":


    As you can see, each of the suggestions is a link, that you just have to click to do what it says. I don't know if and how the suggestions are sorted, but the one I needed was always in the top 2 as far as I can remember. As a comparison, here is what I get in Visual Studio:


    Then I can right-click and choose to resolve the missing reference, or generate a new class or type called Matrix. But this is really not as informative and convenient as what Eclipse does.

    • the bookmark window. I use bookmarks quite frequently to switch between 2 to 5 different places in my code. In Eclipse, I can give a name to each of them when I create them, see them all in a window, and use that window to go to any of them at any time. This seems so simple, and similar to the breakpoint window in Visual Studio, that I was surprised I never saw it there. Quick search on the internet: this window actually does exist in Visual Studio, but is not included in the Express versions of the product. Annoying, but fair enough. By the way, the breakpoint window is apparently included in VS C++ Express (so I read), but not in VS C# Express.

    • the File Explorer tab in the DDMS (Dalvik Debug Monitor Server) perspective. As your game is running in the emulator or on a real phone, you can see what files it creates, updates or deletes, and transfer them to your hard drive to have a look at their content. That's very useful to verify your save game code works correctly, etc.

      In Visual Studio, I don't know a good way of doing that when running a WP7 game (I use the PC version I also have, since XNA is cross-platform, to check my files). And although this is not the subject of this article, this would also be a great feature to have when developing on the Xbox360 with XNA.

      • the DDMS perspective also allows you to take screenshots of your application, whether it's running in the emulator or on a device! I haven't checked the Mango beta of the WP7 tools yet (I cannot install it and modify my setup until I'm done with my current project), but this is something that has been missing since the beginning.

        • the SD card emulation. It's not totally trivial to set it up, but it allowed me to transfer some photos and pretend they had been taken with the phone's camera. This was important to me because Jigsaw Guru allows players to use their own pictures, and in the WP7 emulator you only have a few predefined ones for testing, and they don't necessarily cover all the cases you want to verify as far as naming or dimensions go.

          • this one is more of a detail, but when a source file imports libraries it doesn't need, I get warnings. And when I use the aforementioned suggestion window, or some other automatic way of adding imports without typing them, they are grouped according to the first part of their namespace, and then ordered alphabetically inside each group. Perhaps I'm a maniac, but I like this stuff to stay clean, and basically Eclipse does for me what I manually do in Visual Studio.

            Now let's talk about the things I didn't like as much:

            • when an exception is thrown, it's not as easy as it should to know what happened. Maybe it's because in my case it happened most of the time in the OpenGL thread, but anyway: there doesn't seem to be a call stack window like in Visual Studio, in Eclipse I found after a while that the call stack gets printed in a window in the middle of some other log messages, and that's a mess. Seriously. Especially compared to Visual C#, where the program automatically puts me on the line that generated the exception, with a floating window telling me what the problem was.

            • when you're stepping into your Java code, you cannot move the instruction pointer. I so could not believe it that I did an online search, which confirmed it. Actually, I even ran into some programmers that are so used to it in Eclipse, that they were asking how this can be useful anyway, and why you would want this feature. Oh boy!

            •  if you want to change the value of some variables while you're debugging your code, it's a pain. I don't exactly remember the details, I just remember I gave up after a while.

            • when your program is stopped on a breakpoint, you often want to check the value of some variables, don't you? Most of the time it works, but I got this "JDI thread evaluations" error a lot each time I tried to look at the content of arrays.

            • auto-completion is not the greatest. First, I find it kind of slow. Second, it only kicks in after you've typed a dot character, as in "variable.something". I'm sorry, but Visual C# is an order of magnitude better, and will auto-complete about anything: a language keyword, a function name, or the name of a variable in the above example - if what I'm typing starts like the name of an existing local variable, parameter of the function I'm in, class member, etc. I'm so used to it that I never type "public void" for example, but "pu" + space + "vo"+ space instead. In the long run, this probably saves me from a lot of typos :)

            • I'm not 100% sure about this one, but I got the impression changing a resource file (texture, sound, etc) doesn't trigger a rebuild of the project. 

            • when you have both a warning and a breakpoint on the same line of code, you basically can't see the breakpoint anymore.

            • in the DDMS file explorer, it is not possible to multi-select files and delete them, you have to do it one by one.

            To sum up these pros and cons, I would say that editing code with Eclipse was OK (although improving auto-completion would make it even better), but debugging was rather painful.

            Java versus C#


            I'm afraid this comparison is a bit unfair: not because I've been using C# for several years whereas I was learning Java with this project, but because I was porting from one language to the other. This means I immediately noticed every feature I use in C# that is not available in Java, but I'm not aware of some other features that may be supported in Java and not C#. So, you've been warned, and hopefully the simple fact that I was ready to learn Java somehow shows that I'm not into language flame wars and that sort of things (even if I don't hide I love C#).
             
            The first thing I found out is Java and C# are more similar than I thought. They don't just have many features in common (such as garbage collection, even if it's not necessarily based on the same implementation), the syntax is often almost identical. Some keywords are different of course, but lots of times I could just take my C# source file, copy it into the Java project, do some renaming (replacing "const" in C# with "final" in Java, bool with boolean, override with @Override, etc), compile, and then fix the few errors I was getting. That said, there are also some real differences, and I found some of them truly annoying.

            • The main one is structs. Unlike C++ and C#, Java doesn't have structs (everything is a class). Why is that annoying? Because of the copy semantics of structs versus references. In C#, if I do something like this:

              Vector2 position = otherPosition;
              position.X = 1f;

              and Vector2 is a struct, I'm basically copying the value of otherPosition to initialize my "position" variable, and then I'm modifying the latter. Now since Java doesn't have structs, and I wrote a Vector2 class instead, the same code puts a reference pointing to the same object as otherPosition in my new variable, and then modifies the value of the object referenced both by position and otherPosition. I just modified the object accessed through otherPosition in Java, although I was absolutely not doing that in C#!

              This ended up being the source of most bugs I had to fix in my Android port, because XNA relies on a few structs you use all the time: Vector2, Vector3, Rectangle, Color and Matrix are the ones that come to mind. Of course, I would have overloaded the assignment operator (and a few others) of my Java Vector2 class to make it behave like a struct if it was possible; but Java doesn't support operator overloading.
               
            • Java doesn't have out and ref parameters. Therefore, if you want a function to return more than one value, for example two integers representing the row and column indices of an item in a grid, you need to do it another way. One suggestion I read online is to pass an array to the function (in my example, an array of 2 ints), and I used that method in a few places. But it's kind of a hack, and of course the compiler won't guarantee that values have been set for all the elements of the array, whereas the .NET compiler will tell you if an out parameter isn't assigned a value for some code path in the function.

              • Java doesn't have the equivalent of C#'s properties. It's obviously easy to rewrite them as functions since properties are nothing more than a writing convenience, it just takes some time since any C# program usually has a lot of them (and you also need to change the places where they are called, and add parentheses everywhere).

                • Every function is virtual in Java, and everything is public by default. Seriously? These two points didn't create any problem for me, but I still felt like adding the private keyword everywhere I omitted it in C#. I don't know who had this brilliant idea, but to me it just seems wrong that broken encapsulation is the default, I'm sorry.

                  • Java doesn't have unsigned types. I didn't see that one coming, and I'm still surprised that if you're only dealing with positive non-fractional numbers, you would want to lose half of the range of values you can store in a given type. Weird.

                    • Java cannot do a switch statement on a string. This is a nice addition in C#, for example when you're loading an xml file and need to do different things depending on the value of an attribute you just read.

                      • Java doesn't have delegates (more or less the equivalent of C++ function pointers, but type safe). I'm sure there are a bunch of ways to work around that, mine was to use an interface with just one function, and a nested class implementing it. Then, instead of passing the delegate to a function, you pass an object of the nested class.

                        • Java forces you to declare all the different types of exceptions a function may throw. I found it pretty annoying: if you modify a function, and a new type of exception can now be thrown by the system, all the functions calling the one you modified also have to declare that exception, and so on. Except of course if you catch it at the lowest level, but that's very often not the place where you want to do it. I don't know, C# exceptions work the same way but without these extra declarations, and I can't think of a case where having this feature would have helped me as a programmer.

                          • Finally, simple enumerations are fine, but enums where you want to assign a specific value to each element are not supported. Some people online suggest using EnumSet instead, that seemed a bit overkill to me and I replaced them with a series of constants (which is of course not as good as the original enum, since values that didn't exist in the enum can be passed to a function that now accepts an integer, without the compiler telling me something is wrong).

                            Like I said before, there may be some awesome features in Java that don't exist in C#; but from what I saw, C# is basically a more advanced, more convenient to use, version of Java, thanks to some of the things I just detailed. Anyway, since those languages share a lot of similarities, porting from one to the other is not very difficult, as long as you stay away from the latest additions to C# (such as Linq), and know what to pay attention to.

                            OpenGL versus XNA


                            XNA is based on DirectX, and Android uses OpenGL. Which means I had to rewrite my rendering code. I had not done any OpenGL in about 10 years, but it wasn't too difficult to get back to it: OpenGL ES 1.0 and 1.1 on mobile phones are basically the same thing as what I used on desktops at the beginning of this century, except for glBegin/glEnd that have disappeared for performance reasons. Anyway, I don't really have a preference between DirectX or OpenGL (at least one section where I shouldn't hurt anybody's feelings ;)), but here are a few notes I took:

                            • the OpenGL way of passing predefined parameters to functions is just awful. I mean, seriously, on Android there is this one long list of values such as GL10.GL_PROJECTION or GL10.GL_BLEND, and you can pass any of them to any function since they're all integers, even if most combinations don't make any sense (for example, glMatrixMode(GL10.GL_BLEND)). Where are the enums? (I know, old interface, historical reasons, backward compatibility...)

                            • on Android, you can call the GLSurfaceView.setDebugFlags function to get some logs and add some error checking when OpenGL methods are executed. That's great, until you move from GL ES 1.0 to GL ES 1.1 (to use vertex buffer objects), and discover that gl11.glGenBuffers throws an UnsupportedOp exception when the debug flags are enabled. Meaning they become totally unusable :(

                            • when your application is paused, because another application moves to the foreground, its OpenGL context is destroyed. This means that if it gets resumed later on, you have to recreate all your textures and vbo's, or you will crash. This doesn't happen on WP7, because when the game is tombstoned and resumed, the whole application is restarted, it's not just the rendering context that needs to be recreated! Anyway, since I have written code to handle the Android "application life cycle", and tombstoning on WP7, I don't believe one is more difficult to deal with than the other, both are necessary evils.

                            • OpenGL commands cannot be issued outside of the OpenGL thread. That makes sense, especially once you've been bitten.


                            That's about it. The main difference in fact, is that XNA adds a small extra layer on top of DirectX, and that's what makes it nicer: there are a few classes that are very useful to have, that I had to partly rewrite to make my game run on Android. I'm talking about SpriteBatch (used to batch and draw anything that uses screen coordinates, for example your game's UI), and SpriteFont (used to manage fonts). Yes, unfortunately, if you need to render text with OpenGL ES, it's Do It Yourself.


                            The emulator

                            That's where things become very painful. At first everything looked OK, while I was trying to render a static menu screen, and hook up touch input to navigate to another one. But when I finally animated something, I was shocked to see I was getting 4-5 frames per second, with only a few draw calls and almost no overdraw! Of course I went online, thinking there was something I needed to set up to fix the problem, or something along those lines. Unfortunately, this wasn't the case.

                            The Android emulator does a lot of things, and I suppose it's a decent or even good tool to write apps. Although, I found out many people complain it takes a very long time to start, and isn't particularly fast: this is because it emulates a real ARM architecture, instead of running an x86 version on Windows. But here is the real kicker: it doesn't use hardware acceleration for OpenGL! So, forget about your brand new ATI/AMD or nVidia video card, and suck it up: everything is very slow, even in 480*320, and some 16 bit like banding is visible if you have gradients. Unbelievable.

                            And that's if you use OpenGL ES 1.0 or 1.1. If you'd rather go the native route, and rely on ES 2.0, it gets worse: the emulator doesn't support it, period. Wow, just wow. So, how do people write OpenGL games on Android? Well, the only "work-around" is to use a real device, and never use the emulator. I've put work-around between quotes though, because to me it's a very limited one, for the following reasons:

                            • deploying to a device cannot be a very fast process, which is why you normally want to do most of your work in an emulator to start with. Even if this is not as true on Android, since deploying to the emulator is not really fast either (more on that later).

                            • the emulator allows you to test your program in different resolutions, how do you do that with a single phone? I don't know, I suppose you buy more phones.

                            • the emulator allows you to test your program on different versions of the OS. My phone has Android 2.2, maybe I could retrofit it to 2.1 but even if that's possible I don't want to keep reinstalling it, and what about 2.3 and 3.0 if it doesn't support them? Buy more phones?

                            So, developing on a real device does work, but it won't allow you to test your game in as many configurations as the emulator, and that's a problem. Except maybe if you work for a company, and can get several different phones.

                            Now let's talk about productivity. I noticed two problems with the Android emulator:

                            • launching it the first time is long, but after that you keep it running and just restart your application, which is much faster: this is fine, and the WP7 emulator works the same way. Well, this is fine until the deployment starts failing for some unknown reason, and you have to re-launch the emulator all the time. This happened to me more and more, and I think it has something to do with the size of the apk file: when I finally added music to my game (3 big mp3 files), it basically became impossible to not reboot the emulator each time. I looked online and tried to add some command line parameters, but that didn't fix it.

                            • even when I didn't have to kill and restart the emulator each time, I think I noticed something else: it looks like if you make even the simplest change to your code, let's say you change the value of a boolean variable, the deployment takes 35 seconds. Since recompiling that change takes no time, I'm under the impression the whole (and eventually big) apk file is redeployed, the same way it would after a rebuild all. Whether that's what's happening or not, it sucks: on WP7, if I do a similar change, I don't know how things work (since the xap file is modified, and as big as the Android apk file), but I'm getting a real incremental deployment, meaning none of the assets are sent to the emulator, and that's very fast. On Android, once you know this won't be the case and will probably take at least 30 seconds, you switch to another program, maybe check your emails or start reading something on the internet, and when you finally come back to the emulator, the first thing you do is ask yourself: "what was I going to test, again?". This interruption totally kills your workflow, and productivity drops.

                            There are a few other things I could complain about, that are more related to the libraries than the emulator, such as the pinch gesture only appearing in Android 2.2, which means you have to implement it yourself if you want to support Android 2.1. But those are smaller details, and overall the libraries are very good, so let's move on to the last topic. 


                            Compatibility


                            Hallelujah! Despite the big framerate issues, you made an OpenGL game and everything works fine in the Android emulator. Maybe you even already tried it on a real device, or did the whole development that way, and all you have left is to release the game on the Android market, which is a very fast operation since there is no certification process (unlike on WP7 and iOS). And then you're done (with the development side of things, as long as you're not making an update)! Or are you?

                            No you're not. Even if the program runs fine in the emulator, and on your phone, and on your friend's tablet, there are still many devices that won't run it correctly, or at all. This is the main development problem with Android imho: the platform is open, no two phones are identical, they don't necessarily run the exact same software, some have terrible OpenGL drivers, and therefore being compatible with a decent percentage of the devices currently available on the market is a huge challenge. And new hardware keeps being released every week...

                            To illustrate this point, let me give you two real cases I had with my game:

                            • once the Android port was advanced enough, and I knew I would finish it (rather than give up), I bought a Nexus One, the phone that was recommended for development by Google at that time. First time I tried to run the game on it: everything was white, with a couple of grey squares where I normally have disabled UI buttons. It wasn't too hard to figure out what was happening: the Nexus One cannot handle textures with dimensions that are not powers of 2. Fixing it wasn't difficult enough (I rescale the textures on the fly when I load them), but this shows the fact that the program runs in the emulator, or on some phones, doesn't mean it will run on all of them (even the one recommended by Google!). What I don't understand is why the framework doesn't take care of that, it could totally do under the hood the same rescaling I do, and I would never had known about this limitation.

                            • a player emailed me, saying he used to play on his Galaxy Tab and everything was fine, but now that he moved to a Xoom tablet he cannot save his settings or games. I don't know if this comes from the tablet running Android 3.0, or some different type of storage being used, but it's pretty surprising the file API isn't compatible. I still have to look into it, and since I don't own a 3.0 device, I'll do it in the emulator, even if the OpenGL software rendering is going to make this a painful experience. 

                            Conclusion


                            Developing on Android wasn't a fun experience for me. Like I said at the beginning, it is or is going to be a big market (although, not many independent developers seem to be able to make money on it - yet?), so it's tough to ignore it; but the tools are not at the same level as on the competing platforms, by quite some margin. If Google wants to have more games on Android, and I'm talking about original games and not just ports of iPhone ones many months later, the first thing to do is fix the emulator. I don't care if it fully emulates an ARM CPU, I want it to start faster, run faster, support incremental deployment, use OpenGL hardware acceleration, and that would actually also allow it to support ES 2.0. As far as compatibility goes, this is a more difficult problem to address, and I don't believe it will be fixed anytime soon, since it's basically a consequence of the platform being so (too?) open.