I’m currently developing a hidden object puzzle game with a friend for mobile, tablet and desktop. That’s Android, iOS (iPhone + iPad), a bunch of other mobile type platforms, Windows, Mac OSX, Linux. Targeting all these platforms at the same time, and from the same source code is tough, and I am going to discuss the method that worked for me.
With Terrorhedron, I have been getting frequent emails, tweets and messages from Mac and Linux users asking if Terrorhedron supports their platform. The answer is no, and that really sucks. A bunch of my friends have Mac Books too, and I regret they can’t play it. But more than this, these platforms have really tight communities with a huge appetite for that kind of game.
There are several cooperative gaming communities that really drove the success of Terrorhedron due to their very enthusiastic and loyal support. For these communities, Terrorhedron was a desperately needed game and they really valued it. This niche appeal is a real driver and was very important in generating general interest in the game. I feel as if niche interest could have been easily generated from Linux and Mac communities who have a much lower supply of games.
Marmalade is a c++ API and make-file system for building and deploying to mobile devices. It has a really impressive supported platforms list and is really easy to get started with if you are a c++ programmer. It takes almost all the pain out of developing for mobile, and especially for developing for more than one platform at once. I love working with it because it is such a simple system and has a really powerful and well organized API. You build your program up from a main() function, just like any c++ program.
To extend support for your program to support other platforms, the process is simple. You must group and abstract the Marmalade API calls that you are making to an interface, and implement that interface for both Marmalade and your desktop API. In this case, I am using GLFW, an OpenGL library for Windows, Mac OSX and Linux.
Programming for multiple platforms
This is a typical multi-platform set-up; a common interface, with that interface implemented per platform or per group of platforms. The important point here is keeping it manageable and fast. In this case, I am using two multi-platform API’s to reach all my platforms, with my set of features minimized.
The abstraction of the API is simple, allowing you to create platform non-specific engine and application code
My interface is a pure virtual class, while my implementations inherit from this, providing functionality through virtual function calls. An alternative method would be to use #ifdef #endif to perform compile-time implementation selection which would also be easy and tidy to program, and remove the virtual function calls which will have a small performance impact. I personally favour virtual function calls with inheritance for design reasons, and because I doubt 100 virtual calls or so per frame will have any impact on performance.
The differences between mobile and desktop
I am developing for very different types of platform – mobile and tablet, and then the vastly more powerful desktop. The desktop is feature rich while mobile is much more limited, so the overlap is the mobile platforms features. For this reason, and because desktop has much more processing power compared to mobile, it makes sense for the interface to match Marmalade as closely as possible, and allow desktop to emulate mobile functions.
Will the same game work on mobile AND desktop?
It is important to consider why you are targeting the platforms you have chosen – there is no point targeting desktop if the game doesn’t really work with a keyboard and mouse. The counter argument is – if you can deploy to more platforms, why not? Surely the more the better, as long as a platforms deployment does not constitutive a “bad game”.
Using the above system, I can target those platforms discussed without too much effort, using a couple of hundred lines of code on top of the API’s discussed. I have chosen to use this for one game, while keeping another mobile only, for the reason that I do not want people playing those games on a desktop – because it detracts from the qualities of the game.
For a game to work across so many platforms, it has to be simple in terms of interface and mechanic. For me, that is great because it is kind of what I am about anyway. For more complex games, the effect may be that it works well on mobile but leaves a disappointingly average experience on desktop.
Variance between platforms
For desktop, you can easily add extra graphical effects using #ifdef DESKTOP etc. My intentions are not to deviate any more than this between versions in order to keep the design and implementations as simple and uniform as possible. Keeping the design manageable is of key importance.
A more experienced developer than myself would probably tell you not to underestimate the importance of testing on each platform. I don’t really understand this and don’t expect to until I have actually released a product across the above platforms but remain optimistic. I plan to send my various internal releases out to friends to cover the full range of platforms to avoid any major surprises but am unsure how testing will work out. With such a narrow API interface, surely the majority of platform specific bugs will be glaringly obvious?
Keep your setup as simple as you can, make sure you are familiar with your API’s and understand what you expect from them. Design your game with the distance between mobile and desktop in mind and analyse the effect and value of what you are achieving. micromacro