tl;dr: In the first part of this article I wrote about the motivations and the first steps I made to port the LÖVE engine to Android. Here I write about some technical difficulties that were solved and a few very interesting features the port now has. Also I created a small incomplete list of people who have contributed to this port.
I was really stoked when I saw the nogame screen the first time on my phone. A big helper for this was the GLES port of @slime73. There was almost no change required to get this far. The next thing up was to load an actual game. For this I had to somehow load the game. Undearneath LÖVE use physfs and comes with a custom wrapper for it. After some experiments I figured out that the Android NDK supports standard file I/O to the sd-card if you give the App write permissions to external storage (i.e
android.permission.WRITE_EXTERNAL_STORAGE). With this knowledge in hand I implemented loading of the game found in
/mnt/sd-card/lovegame. This allowed me to start my game on the phone without having to change a single line of the original Ludum Dare submission:
— Martin Felis (@fysxdotorg)
Running the game unveiled a bug in the GLES code when pushing new transformations but the fix was simple. From that on the game “just worked”. Including audio for which I did not have to change a single line of code!
Now the port seemed it a very capable state. Something essential that was missing was creating a game Android package of the LÖVE engine + game into a proper Android package. I could already load games that were placed to
/mnt/sdcard however LÖVE games are usually distributed either with the LÖVE binaries as OS specific packages or as
.love files which is simply the game project folder packed into a zip file. Also LÖVE can directly load .zip files to run the games contained in them.
On Android on the other hand Apps can only open files that are stored in the
assets/ folder. Luckily SDL2 allows accessing files in the assets folder without much hassle using the SDL_RWops. To create a packaged I simply added the
game.love file to the assets and when starting the App it would open the file using SDL_RWops and copy it to the internal storage and then load it using the standard LÖVE code. While this worked well this has the huge drawback that games would consume twice the memory: in the package’s
asset/ folder and then in the internal storage. I could have tried to delete the latter when exiting the app but this didn’t work reliably enough.
Instead inspired by a hint of @slime73 I switched to the inofficial 2.1 code of physfs (which can be obtained using the official physfs merurial repository). Physfs 2.1 comes with PHYSFS_mountMemory that allows to load archives from memory instead of actual files, which works perfectly. I still have to copy the game from the
assets/ directory into a memory buffer but it is much nicer and also uses less overall memory in the app statistics. (Physfs unfortunately introduced a bug but that is avoided in my port using a small hack).
Another improvement that I wanted to do was to use LuaJIT instead of stock Lua. I had started with the latter as I wanted to first get things work and clean up things later. LuaJIT (which is also the now default in LÖVE) has quite a performance advantage in many cases over standard Lua — even on ARM. Setting up LuaJIT for the LÖVE port was quite a hassle. It comes with its own build system that I did not manage to integrate into Android’s NDK build system unfortunately. Eventually I resorted to adding the LuaJIT binaries to the repository along with a small script that builds it using the LuaJIT build system and the required Android specific parameters.
When testing LuaJIT with the LÖVE code unfortunately I had worse performance than using standard Lua. It took me a long time to figure out what might be the cause for it. To be honest I am still not entirely sure what exactly, however when reading this thread I tried the older 2.0.1 version and I could finally enjoy the performance gains. One nice thing about Android is that the JIT part of LuaJIT actually works.
As far as I know Apple sadly prohibits code generation on iOS which makes JIT impossible (see comment about iOS at http://luajit.org/install.html).
The build system for the external libraries was created using @schattenkindnet‘s older port. Some of the libraries that LÖVE uses have been updated since then and so I went on to update them. For some it was a lot of work to figure out which compiler flags were actually required or parts of the files were created during the build system which then again made me cross compile code using autotools (scary!) and extract files. Openal-soft was also challenging as it used CMake for which a CMake Toolchain script had to be used to create the proper configuration header files.
Eventually I ended up with all the files required such that I could use Android’s
ndk-build to build everything (except LuaJIT). In the same time I also made sure that I link against all LGPL libraries dynamically whereas everything else is linked statically to reduce the binary size. Updating the libraries was worth it as also fixed audio performance.
It wouldn’t be a proper mobile game engine if it didn’t have a touch API. I received a patch by piernov which fixed this. Eventually this code was replaced by the
love.touch that was introduced to the experimental repository shortly afterwards and aims to be compatible with a future iOS port.
Additionally to the more or less technical things above the LÖVE port has a few very nice additions:
Accelerometer as Joystick: instead of adding a special sensor API read the accelerometer using SDL’s joystick API. This involved fixing a bug in SDL2 which was done by Jairo Luiz
Icon: Seppi (@josefnpat) created a fantastic logo out that mixes the Android with the LÖVE logo:
File Association: Since beta2 the Android LÖVE App adds a (somewhat experimental) file association. At least using Chrome mobile it lets you download
.love files from the web such that you can open them from your Downloads activity. Also
.love files attached to emails can be opened directly using the LÖVE App. Large parts of this was also made by Jairo Luiz
Game Editing on Device: Since LÖVE uses Lua and the code gets compiled/interpreted on run-time it allows for editing the game on the device itself without a host computer. Heck! It would even be possible to create whole games on the Android device without a PC!
Sensible Default Mappings: A touch event is reported as a left mouse button event. The back key maps to the
escape key. For simple games this is sufficient to make it work.
I am currently working on getting my game released on the Google Play Store. It has been approved already and but I at the moment I am cleaning up some edges. But I hope to release it soonish to the public. Follow me on twitter or subscribe to the blog and you’ll get notified.
Also publishing the LÖVE App via the play store would be an idea. Maybe with some kind of launcher to simplify running of different games?
This all was only possible due to the fantastic works of others. Even though the risk is extremely high that I will forget valuable contributors I want to list some (let me know if I missed someone or something):