Friday, August 14, 2015

LibGDX - Game and Screen classes: an introduction

The goal of this post is to present Game and Screen classes and how they can be used together.
Their lifecycles are highlighted using logging capabilities.

Through Game and Screen classes, it is possible to split logic and visualization: the Game class will contain the logic, while the visualization could be organized in several screen classes (one for the game itself, one for high scores, on for help...).

The Game class will manage the screen changes.

Example source code

You can download source code from github:
    https://github.com/mytechpg/libgdx-samples.git
    Branch: dev
    SHA: 83172b11f1a456395a35a2c2505837a60d044cdf

Main classes: MyGame and MyScreen

If you look in the logging-core/src directory, in the package com.blogspot.mytechpg.libgdx.test1, you can find these classes:
  • MyGame that extends Game
  • MyScreen1 that implements Screen
  • MyScreen1 that implements Screen
Game class implements ApplicationListener, than it could be used as the main class of your program; the visualization is delegated to Screen, so you can use it to implement games with several user interfaces.
Game class offers the method setScreen() to set the Screen that has to be displayed.

In this example, there are two Screen classes, one with a red background, the other with a green background. The switch between the two classes is triggered by the resume method, as you can see looking at the log.

public class MyGame extends Game {
MyScreen1 scr1 = new MyScreen1();
MyScreen2 scr2 = new MyScreen2();
int scr = 1;

@Override
public void create() {
Gdx.app.setLogLevel(Application.LOG_DEBUG);
Gdx.app.debug("Game-Screen", "MyGame: create()");
scr = 1;
setScreen(scr1);
}

The method show() of Screen is very important, since it is automatically called when a Screen is displayed, then you can use it to initialize variable.

public class MyScreen1 implements Screen {
SpriteBatch batch = null;
Texture img = null;

@Override
public void show() {
Gdx.app.debug("Game-Screen", "MyScreen1: show()");
if (batch == null)
batch = new SpriteBatch();
if (img == null)
img = new Texture("badlogic.jpg");
}

The rendering is delegated to Screen classes, so you have to put the code to draw the user interface directly in MyScreen1 and MyScreen2.

@Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(img, 0, 0);
batch.end();
}

How to test

To test the new logging release you have to change the desktop and android classes, replacing "new Logging" with "new MyGame":

  • Desktop: you have to modify DesktopLauncher class, at line 12. The new version is:
                    new LwjglApplication(new MyGame(), config);
  • Android: you have to modify AndroidApplication class, at line 14. The new version is:

                    initialize(new MyGame(), config);

Desktop launcher

public class DesktopLauncher {
public static void main (String[] arg) {
LwjglApplicationConfiguration config = 
new LwjglApplicationConfiguration();
config.width = 600;
config.height = 400;
new LwjglApplication(new MyGame(), config);
}
}

Android launcher

public class AndroidLauncher extends AndroidApplication {
@Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = 
new AndroidApplicationConfiguration();
initialize(new MyGame(), config);
}
}