Rocket Riot is an action-packed, side-scrolling, 8-bit shooter that was originally released in June 2009, and later updated and ported for release on Steam and the Universal Windows Platform (UWP) in October 2016. This was when I worked at Codeglue, and was given the task to port the game to a new platform: Android. Rocket Riot is written in C++, and since it was aimed for Windows, DirectX was used for the graphics. Android devices do not support DirectX, making this quite the challenge to port.
This is how Rocket Riot looks on the PC:
To start of I did research to development of Android apps with C++ code. For the Lights Out Android game that I made earlier, I used Marmalade, but this wouldn’t be an option for Rocket Riot. I found Android Studio, gradle, and Xamirin, and Visual Studio seemed to have some experimental support for Android at the time too.
Comparing them by only comparing the information that you can find about them isn’t the best way to cut it, so instead I tried to set up new projects to see how convenient the toolchains work.
Once I got a project running from Visual Studio that would launch the project on the connected Android Phone, I could start to port the actual game. I added the new Android Project to the Rocket Riot Solution, and added all its source files to its compilation unit. Boom. Thousands of errors. But that was expected. The source files use DirectX, which is not available for Android. I went through all the files one by one to surround all DirectX related parts with preprocessor blocks, to skip them from compilation. Eventually, all source files would compile, but still have to link properly. This was pretty straight forward, for each function with a declaration but no definition, I just created a dummy function that does nothing in the Android project.
The app launched, and I saw the same blue screen as before, though it was a huge step forward.
The next step is to render something of the actual game to the screen. Since the splash screen is the first thing that gets launched, it’s what I decided to implement first.
Alright, we got primitives. Now to load textures.
Texture loading proved to be more difficult that expected. The PNGs have to match a very specific format in order to load correctly. Running them through PNGGauntlet seemed to fix it for most, though some edge-cases (e.g. single channel/grey-scale images) didn’t work properly.
An interesting difference between DirectX and OpenGL is the coordinate system. It’s why the textures appeared upside down at first. This was simply solved by adding a camera matrix – that was needed to fix the coordinates anyway – and making it flip everything vertically. The textures now appeared correctly, and the splash screen was working. The main menu was still a different story, though. This is also where the user input would need to be handled.
Through the Java Native Interface (JNI), any input data that the Main Activity records can be send to a a function whose declaration is in Java and its definition in C++. From there, you can send the data to the handlers in C++ to handle it. The most annoying part is to make sure the function signatures match, since the JNI automatically adds some information to the function name that you need to reflect on the C++ side.
Once the user input was handled correctly and the camera’s view matrix was set right, the main menu worked already for the most part. Touching buttons would change the menu state, you could switch between different, and you could even start the tutorial! Now for the scary part: testing it on another device.
Unfortunately, the game didn’t render the same way on all devices that I tested. Loading of textures seemed to work right, but somethings looked… just weird.
Since I was only able to reproduce these issues on some phones but not on others, debugging became more of a challenge. Fortunately, the Android toolset includes a tool called Android Device Manager, that can help you inspect what’s happening on the device exactly. With it, you can record OpenGL calls and see its state between every one of them. Recording makes the game run very slowly, just one frame every few seconds, but it provides a lot of details.
This tool quickly became my friend. I found that the order of the buffers is reversed on some devices, which caused most of the issues. By explicitly stating buffer IDs and by retrieving them from OpenGL calls when creating a buffer, instead of relying on the order, most of the issues were fixed already. Then it was only a matter of tracing the smaller ones, and one by one they got all fixed, and the game looked the same on all devices that I tested it on.
Some screens of the finished product:
This entire project took me around 3 months. Before I started, I had little experience with Android development, and I learned a lot from it. Near the end of the project, two colleagues joined in to help finish things up before I went back to school. We made a list of things that still needed to be done, and this was a very enjoyable time for me, mostly because