One of the best features of LibGDX is its ability to develop for several platforms (Windows, Mac, Linux, Android, iOS and HTML5) with a single code base. And while it does an amazing job at hiding the differences between the platforms, it can only go so far. Certain specifics can’t (and shouldn’t) be handled by LibGDX, but by the developer. Proper in-game input handling and the user interface, to name examples. Android and iOS devices typically lack a keyboard and use a touch interface instead of a mouse. The developer must account for these differences.

LibGDX offers a way to programmatically determine the platform at runtime through Gdx.app.getType(), returning Android, iOS or Desktop. And while that works for many use cases, it clutters the code and very much reminds me of the old C/C++ #ifdef macro shenanigans. Furthermore, for some cases, it is not even applicable: when porting a LibGDX game to iOS, many libraries and classes that are available on Java simply can’t be used because they are not supported by the build process (see this blogpost for further information on what is and what isn’t possible/available). What that means in practice is that if we want to port to iOS, our main project where most of the code resides needs to be agnostic of all the stuff that’s not available on iOS. For example, in my game “Rico – A Tale Of Two Brothers”, I use XML to store the levels and the player’s progress and settings. For Java, I can leverage SAXParser, which comes with the JDK. Unfortunately, that’s not an option for iOS/Monotouch because IKVM simply doesn’t support it. But before I step into how I solved these issues, let me raise another.

Many games have more than one “editions” or “versions”. In addition to the full version, on Android, there’s often a “lite” version that offers only a part of the game. On the Desktop, people would rather call it a “demo”. For “Rico – A Tale Of Two Brothers”, I also had to create a special build for a game bundle (I called it “bundle version”, how original!). And as a bonus for people who bought the game at IndieGameStand I created an edition that featured four extra levels not available in the main game. All in all, I have 8 different manifestations of the game. Creating all these versions while still retaining a single code base posed a problem.

Introducing: the facade pattern

Rummaging around in our design patterns box o’tricks, we find a pattern that can help use resolve all the aforementioned issues: the facade pattern. Quoting Wikipedia,

[a facade can] reduce dependencies of outside code on the inner workings of a library, since most code uses the facade, thus allowing more flexibility in developing the system

How can we leverage this pattern to help us? Let’s start by defining the facade’s interface:

01
import xml.IXMLReader;
02
import xml.IXMLWriter;
03
 
04
interface IFacade {
05
 // define the type and the getter to query the edition at runtime
06
 public enum Edition { Full, Lite, Bundle, Bonus }
07
 public Edition getEdition();
08
 
09
 // define the getters for the XML-reader and -writer implementations
10
 public IXMLReader getXMLReader();
11
 public IXMLWriter getXMLWriter();
12
 
13
 // define the getter for the input-scheme
14
 public IInputScheme getInputScheme();
15
}

Notice how the getters for the XML-reader, -writer and input-scheme only return platform-agnostic interfaces and not classes that might contain code not available on both platforms (Java and .Net/Monotouch). I omit the code for these interfaces (and their implementing classes) as they are only examples and not the focus of this post. Also note that these are just examples of functionality you can encapsulate with a facade.

If you’re familiar with LibGDX, you know that in your main project, you define a class that implements ActionListener, from where the game starts off of. To make the facade available in our code, we pass it into this class in the constructor:

01
public class Game implements ActionListener {
02
 
03
  private final IFacade f;
04
 
05
  public Game(IFacade f) {
06
   this.f = f;
07
  }
08
 
09
  // ...
10
}

We can now use the interface however and whenever we like in our main code-base. 

The “official” LibGDX project setup recommends one core project with the source code and an additional project for each platform the game should be running on. With my games, I took it a step further! I’ve got a project for every combination of version and platform. And each project has its own implementation of the IFacade interface and its methods and the classes it provides. For example, for the Android lite version I’ve got a separate project, containing a class named AndroidLiteFacade that provides Android-compatible implementations for the XML-reader and -writer. And it makes the getEdition-getter return Edition.Lite. A class object of AndroidLiteFacade then gets passed in when constructing the Game class object:

01
public class GameAndroidLite extends AndroidApplication {
02
    @Override
03
 public void onCreate (android.os.Bundle savedInstanceState) {
04
        super.onCreate(savedInstanceState);
05
 
06
        AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
07
        // set config object as you see fit
08
        // ...
09
 
10
        initialize(new Game(new AndroidLiteFacade(this)), config); // pass in the proper Facade object
11
    }
12
}

To avoid having duplicated code in each facade implementation, I set up additional projects that contain abstract implementations. For example, a Java-project that contains an abstract JavaFacade class and implements all the code that’s common for each Java-based platform. Which is essentially every platform except iOS. Here is an UML diagram that shows the (almost) complete facade tree:

UMLFacadeNote that the classes DotNetFacade and iOSFacade are implemented in C#. During the build process for iOS, the Java-interface is also made available as a .Net-interface and can be implemented in C#.

Conclusion

For “Rico – A Tale Of Two Brothers”, the iOS port was developed later than the others. And until then, I had XML classes sprinkled throughout my codebase. To make the code work under Monotouch, I had to refactor a lot of code to make it agnostic to the XML implementation, amongst other stuff. The facade pattern helped me a great deal and when all was done, I had a much more readable and maintainable codebase. Another advantage is that this setup helps me in future projects. I can re-use the implementations for each platform without changing anything.

The facade pattern helped me structure my code better and support multiple versions of the game on multiple platforms, each with its own peculiarities. All that while still maintaining a single codebase.