Native game on Android – Porting Quest of Dungeons
Quest of Dungeons was made in C++ and OpenGL, it runs on Windows, Mac and Linux in native code. iOS is not a problem either since I just have a thin layer of Objective-C to access some functionality like touch, accelerometer, etc and the rest of the code just runs.
I never made anything for Android, in fact I never even used one before this, so when I decided to port QoD to it, I had no idea of what to expect.
Back in 2010 I did some research and the NDK was pretty bad, I don’t think it even had stl at the time, but things have changed since then. I decided to jump in and try to port the whole thing. As a primary goal I want to keep as much native code as possible, because it’s already working, porting it to Java could only lead to further bugs in the process.
After some digging I found that you can use Visual Studio to code for Android (oh happy dayyy).
Visual Studio 2010: http://www.visualstudio.com/pt-br/visual-studio-homepage-vs.aspx
My next concern were some dependencies that I have on the other versions:
OpenAL – for sound card access
Fortunately all of these were possible to compile to Android.
As an entry point I used android_native_app_glue which comes with the NDK, this way you can skip all Java (I have 0 lines of java code in the game)
Another important thing is this line, telling our manifest file that we have no Java code
Usually you just need to do fopen(filename) to open a file. For each platform I would just have to concern with knowing the root folder of where the resources are. But Android works differently, all resources are compressed and you need to use AAssetManager to load them. This proceeds to unpack the file and retrieve a pointer to it. At least this is what I managed to understand from the process.
But this caused a big problem, some of the dependencies, like TinyXML receive a string and proceeds to load file file using fopen(). This meant remaking all frameworks, which is not a very good perspective.
Now every fopen will be replaced with android_file_open
As for the function itself it will try to open the file with AssetManager and return a FILE*
Now just adding this line to the makefile to force the game/libraries to pre-include our file before everything else
So now all my fopen code works perfectly without any change.
I was using GLES for the iOS version already so I had no problems with the code itself, I did however had some problems with performance on older devices, for example 2010 devices with version 2.3 (the game targets 2.3+)
Especially on this function glCopyTexSubImage2D.
The game uses some 2d soft shadows for giving a nice atmosphere, it’s updated once in a while and I just used glCopyTexSubImage2D with a 256×256 texture instead of a VBO because it worked perfectly on everything else (including all iOS devices), but turns out this is very slow on older Android devices, so I ended up adding an option to the game to disable those effects. This way, newer devices can have all bells and whistles and older devices can still run the game fine. One of the testing devices was a Samsung Galaxy S1 and it went from 5 FPS to 30, which is more then acceptable to play. All 4.0+ devices should have no problem running this, and even if they have they can just disable the option.
There is a strong possibility the GL view is trashed when the app goes to background, to save resources the view is recreated each time you go back from background to the app. This poses a problem since all gl objects, textures, shaders, VBOs are destroyed too. There is no secure way to ensure the view never gets destroyed while your app is running so I had to make sure each time the view is recreated I re-load all required assets once again. Really not happy with reloading everything again but its the only secure way, if you detect the view was destroyed and the app is still running you have no other choice. For this game it’s not a big deal, I have few resources and they are fast to load so the user can’t even tell. If I had a bigger game with lots of big textures I would probably had to show a loading screen again.
The different screen sizes for Android can pose a problem, but you can detect screen density and size and scale your game or take proper actions according to what you have.
You can use screen size to detect if the current device is a tablet or a phone.
Now that I finished the port it doesn’t seem that I had to change that much, in fact the game code it self is nearly untouched, just the engine was altered to accommodate for Android. Porting took me ~ 2 months (I have a day job) and while working on a expansion for the game. It’s not all chaos in the Android universe, although the hardware fragmentation poses some very serious problems, some devices may be too slow to run even the simpler games.
If you have questions about anything else I didn’t cover on this article, feel free to ask.