Error in runnable “Creating Gradle model”

While switching from LibGDX 0.9.9 to version 1.0.0 we also switched to the new gradle buildsystem.

However while importing the projects into Eclipse, we suddenly got the following error:

Error in runnable "Creating gradle model"
Unable to start the daemon process.
....
Error occured during initialization of VM
Could not reserve enough space for object heap
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occured. Program will exit.

This might be due to the fact that we added all possible extensions to the projects and generated all possible platform projects as well. In total: It’s just too much for gradle with the default settings.

This is really a gradle problem, no Eclipse problem. It can be solved by creating a gradle.properties file in the root directory of your new project with the following content:

org.gradle.jvmargs=-Xms128m -Xmx256m

Maybe even more, depending on complexity of your build model.

Convenient game architecture with LibGDX

Writing a game is often something very dynamic. Not all features are known at the beginning and the game changes with time. It is important to have code that is easily changable and extendable. At the same time the code should be easy to understand since that reduces the amount of bugs drastically.

That’s why it is very important to have a convenient game architecture which satisfies all of those requirements.

Our approach in achieving something like this, is via the (limited) use of public static variables.

Note: The full code displayed here can be found here on our public GitHub repository. Feel free to clone/fork it and use it as the base of your next game.

Dividing the game

libGDX offers a very nice way of dividing an app into several parts. Via a Game and Screen this is a piece of cake. If you don’t know how this works, you can quickly read about it in this a bit outdated wiki. However in contrast to that article, we are not going to pass a Game around to every Screen and subscreen but instead do it the following way:

public class ArchitectureExample implements ApplicationListener {
    // create a new game and set the initial screen
    public static Game game = new Game() {
        @Override
        public void create() {
            setScreen(new SplashScreen());
        }
    };

    @Override
    public void render() {
        // we just forward all methods to the game
        game.render();
    }

    ... // the rest of the callbacks like resize()
}

This way the main application class (in this case called ArchitectureExample) is not a Game itself, but instead keeps a public static Game variable, which is accessible from anywhere. The ApplicationListener just forwards everything to that game as one can see in the render() method.

Platform specific code

libGDX supports a bunch of different platforms. In case that one of many of them need some individual handling, one needs to add platform specific code. How this works can be seen in this wiki article. Again: we aim for a convinient architecture. Thus we won’t have several interfaces, but one global “entry” interface PlatformSpecific which will again be available public and static, since nearly all possible use cases for platform specific code will fit very well into this “pattern”. This of platform specific methods like showBannerAd(), hideBannerAd(), unlockAchievement(int highscoreId), postHighscore(int score) or login() (which would perform a login into Google Play Services, Steam or any other network). All of this could be called anytime and thus needs to be accessible from anywhere. In code this will look like this:

public interface PlatformSpecific {
    void login();
    void showBannerAd();
    void hideBannerAd();
    void unlockAchievement(int highscoreId);
    void postHighscore(int score);
}

public class DesktopPlatformSpecific implements PlatformSpecific {

    ... // desktop specific implementation of all methods

}

public class ArchitectureExample implements ApplicationListener {

    public static PlatformSpecific platformSpecific;

    public ArchitectureExample(PlatformSpecific platformSpecific) {
        LibgdxUtils.platformSpecific = platformSpecific;
    }

    ...

}

public class DesktopLauncher {
    public static void main(String[] arg) {
        LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
        new LwjglApplication(new ArchitectureExample(new DesktopPlatformSpecific()), config);
    }
}

Running the desktop application now will supply the desktop specific implementation to our core. It looks very similar for the Android, HTML or iOS projects.

Logging

Another global task in a game is logging. Using System.out.println(...) is usually considered a bad practice. libGDX offers Gdx.app.log(...) to do logging, as well as the Logger. In order to not always having to resupply the application tag, we decided to use a Logger instead, which looks like this:

public class ArchitectureExample implements ApplicationListener {

    public static Logger Logger = new Logger("ArchitectureExample");    

    @Override
    public void create() {
        logger.setLevel(Logger.DEBUG);
        ...
    }

    ...

}

This way it is also very easy to globally disable logging by setting another log level (for example Logger.NONE to turn logging off completely when releasing a game). To log something, you can now do the following: ArchitectureExample.logger.debug("Very important debug stuff...").

Asset management

As always, libGDX natively delivers a great solution for this. Namely the AssetManager.

public class ArchitectureExample implements ApplicationListener {

    public static AssetManager assets = new AssetManager();

    @Override
    public void create() {
        Texture.setAssetManager(assets);
        ...
    }

    ...

}

With this, we can now access all our loaded assets anywhere and anytime via ArchitectureExample.assets.get("path/to/asset/texture.png", Texture.class) (for example). It couldn’t be more convenient.

Convenient Batches

To render anything in libGDX, you need to use a Batch. Those will be needed in a lot of places and since they are a pretty “heavy” object, there should only be a single one of them. That’s why it also makes sense here to have a public static one. Just make sure to initialize that one in the create() method, since libGDX has to be initialized before any Batch can be instantiated.

public class ArchitectureExample implements ApplicationListener {

    public static SpriteBatch spriteBatch;
    public static ModelBatch modelBatch;
    public static DecalBatch decalBatch;

    @Override
    public void create() {
        spriteBatch = new SpriteBatch();
        modelBatch = new ModelBatch();
        decalBatch = new DecalBatch();
        ...
    }

    ...

}

Use those batches any time you need to render something.

Internationalization (I18N)

One of the latest versions of libGDX has brought a cross-platform internationalization system. Namely the I18NBundle class. This is also a very good example of something that we keep unique and access globally.

public class ArchitectureExample implements ApplicationListener {

    public static I18NBundle messages;

    @Override
    public void create() {
        messages = new I18NBundle("messages/general");
        ...
    }

    ...

}

If there is is messages/general.properties file in your assets folder, you can now access those messages/texts from anywhere in your game. For example to set the text of a button in your main menu we could use ArchitectureExample.messages.get("Button.newGame") and have an entry Button.newGame=Start Game in our properties file. For a more detailed explanation of how this I18N system works, visit the wiki.

Conclusion

The keyword static has to be used with caution. Especially on Android static objects might behave different than other ones. Furthermore the usage of static generally increases the amount of coupling between classes. That’s why you need to be careful when making something static. Despite that, globally available objects are very convenient and they can drastically reduce the amount of parameters that you need to drag from one class to another. The explained uses of static in libGDX are battle tested and did not cause us any problems. However they made our coding a bit more efficient, easier to read and easier to extend!