You are on page 1of 47

Introduction

Libgdx version used on this post: 0.9.2 (download)

Developing games is a very difficult task, even if you want something simple. There are
many technical concepts to grasp and then you must learn how to implement them
correctly and efficiently on your game's target platform. This is the first post of a tutorial that
I'll write about libgdx - an open source high-performance Java framework for developing
games. A very cool feature of libgdx is that your game can run on your desktop computer
(and that's not using the emulator), which eases the testing and debugging process. Then
you can make it run on an Android device just by writing one line of code. You can even
distribute your games as an applet or via Webstart if you want so. Some features of libgdx
are implemented using native code (like physics and audio processing functions), which
optimizes its execution at runtime.
So libgdx seams to be a nice gaming framework, but what does it provide? I'll highlight its
main features:

An API for OpenGL ES (texture, shaders, vertex arrays and so on)

An API for 2D graphics (bitmap fonts, sprites, UI widgets, animations and so on)

An API for 3D graphics (OBJ and MD5 loaders, camera manipulation and so on)

An API for I/O (audio, files, graphics, key/touch/click events and so on)

An API for physics (box2d) and math

Many utilities (JSON, bitmap font generator, texture packer and so on)
OpenGL ES is a royalty-free, cross-platform API for full-function 2D and 3D graphics on
embedded systems - including consoles, phones, appliances and vehicles. It consists of
well-defined subsets of desktop OpenGL, creating a flexible and powerful low-level
interface between software and graphics acceleration. OpenGL ES includes profiles for
floating-point and fixed-point systems and the EGL specification for portably binding to
native windowing systems. OpenGL ES 1.X is for fixed function hardware and offers
acceleration, image quality and performance. OpenGL ES 2.X enables full programmable
3D graphics.
The OpenGL ES 1.0 and 1.1 API specifications have been supported since Android 1.0.
Beginning with Android 2.2 (API Level 8), the framework supports the OpenGL ES 2.0 API
specification.

Installing libgdx
I'm considering you've already installed Java, Eclipse and the Android SDK, and everything
is working perfectly. Now is the time to download libgdx. I'm using the latest version
available for now: 0.9.2. Now, instead of going through all the installation steps involved, I
want you to watch this video on YouTube. The guy on the video is Mario Zechner, writer of
the Beginning Android Games book and the main programmer of libgdx. He'll guide you
through the basic steps to setup some projects on Eclipse that use the libgdx framework.

Setting up the projects for our game


We'll implement a game together like Tyrian. I used to play this game a lot when I was a
kid, so I'm really looling forward to what we'll achieve. Of course that our final result will be
much simpler than the actual game, but that will do to learn how a game is created using
libgdx. The game will improve as I write new posts for the tutorial. I'll put all the source code

on Google Code, so you can easily check it out using a Subversion client, or just browse it
with your browser.
Okay, so let's start off creating our projects. I followed Zechner's instructions on the video
and came up with the following project structure on Eclipse:

The tyrian-android project depends on the tyrian-game project. This dependency is


configured in the "Java Build Path > Projects" section of the tyrian-android project's
settings. But it isn't enough. On the tab "Libraries" you should manually add the "gdx.jar" of
tyrian-game. Should you skip this step, the game won't run on an Android device (although
it will compile without errors). With this project structure created, you can run the tyriangame on your desktop computer to develop it, and sometimes run the tyrian-android
project on your Android smartphone/tablet to check if everything is going well.

Where to put resource files?


Eventually we'll need to add audio and image files to our game. These resources should be
accessible by both our projects. Instead of duplicating the resources, there is a cool trick
we can do in Eclipse. Note that our Android project has an "assets" folder. By the time we
have some resources, we should put them in this folder. In order to share these resources
with the game project, we create a "linked" source folder. Open the game project's settings
and click the "Link Source..." button as follows:

The game's main class

At
the
simplest
form,
a
game's
main
class
is
an
instance
of
com.badlogic.gdx.ApplicationListener in libgdx. You should get used to read the Javadocs
of libgdx's classes, because many details won't be covered here. Tip: the source code for
the libgdx's JARs can be attached to our projects.
Your game's main class is responsible for handling specific application events, like "create",
"render", "dispose" and so on. The events fired on the desktop don't have exactly the same
behavior when the game is executed on Android, but they're quite similar. The following list
shows the application lifecycle events that can be fired, and when it happens:

create - Fired once when the application is created.

resize - Fired every time the game screen is re-sized and the game is not in the
paused state. It is also fired once just after the create event.

render - Fired by the game loop from the application every time the rendering
happens. The game update should take place before the actual rendering.

pause - Fired just before the application is destroyed. On Android it happens when
the home button is pressed or an incoming call is happening. On desktop it's fired just
before disposal when exiting the application. This a good time to save the game state on
Android as it is not guaranteed to be resumed.

resume - Fired ONLY on Android, when the application receives the focus.

dispose - Fired when the application is being destroyed. It is preceded by the


pause event.
In order to capture and handle these events, you implement the methods of
thecom.badlogic.gdx.ApplicationListener interface. You should also know that when libgdx
creates our game, a separate thread called Main loop thread is created and an OpenGL
context is attached to it. All event processing executes within this separate thread, and not
within the UI thread.
Enough reading. Let's create our game's main class. Please have a look at the following
code and read the inline comments.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

package com.blogspot.steigert.tyrian;
import
import
import
import

com.badlogic.gdx.ApplicationListener;
com.badlogic.gdx.Gdx;
com.badlogic.gdx.graphics.FPSLogger;
com.badlogic.gdx.graphics.GL20;

/**
* The game's main class, called as application events are fired.
*/
public class Tyrian
implements
ApplicationListener
{
// constant useful for logging
public static final String LOG = Tyrian.class.getSimpleName();
// a libgdx helper class that logs the current FPS each second
private FPSLogger fpsLogger;
@Override
public void create()
{
Gdx.app.log( Tyrian.LOG, "Creating game" );
fpsLogger = new FPSLogger();
}
@Override
public void resize(
int width,
int height )
{
Gdx.app.log( Tyrian.LOG, "Resizing game to: " + width + " x " + height );
}

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

@Override
public void render()
{
// the following code clears the screen with the given RGB color (green)
Gdx.gl.glClearColor( 0f, 1f, 0f, 1f );
Gdx.gl.glClear( GL20.GL_COLOR_BUFFER_BIT );
// output the current FPS
fpsLogger.log();
}
@Override
public void pause()
{
Gdx.app.log( Tyrian.LOG, "Pausing game" );
}
@Override
public void resume()
{
Gdx.app.log( Tyrian.LOG, "Resuming game" );
}
@Override
public void dispose()
{
Gdx.app.log( Tyrian.LOG, "Disposing game" );
}
}

Notes on the above code:

As stated previously, our game's main class is just an instance


ofcom.badlogic.gdx.ApplicationListener.

With the FPSLogger class it gets easy to output the current FPS each second, so
we have a feel about our game's performance.

The Gdx class holds singleton instances of many modules: graphics, audio, files
and so on.

By calling the Gdx.app.log() method you can log messages in a cross-platform


manner.

The render() method just clears the screen with the color green.

Running our game


If we're able to run our game on different platforms, we need one specific launcher for each
one. Let's start with the desktop launcher. Please have a look at the following code and
read the inline comments.
?

1
2
3
4
5
6
7
8
9
10
11
12
13
14

package com.blogspot.steigert.tyrian;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
/**
* This class simply creates a desktop LWJGL application.
*/
public class TyrianDesktopLauncher
{
public static void main(
String[] args )
{
// create the listener that will receive the application events
ApplicationListener listener = new Tyrian();
// define the window's title

15
16
17
18
19
20
21
22
23
24
25
26

String title = "Tyrian";


// define the window's size
int width = 800, height = 480;
// whether to use OpenGL ES 2.0
boolean useOpenGLES2 = false;
// create the game
new LwjglApplication( listener, title, width, height, useOpenGLES2 );
}
}

That's all. If you run this class, you should be able to see the following result:

And for the Android devices, you can create an activity like this:
?
package com.blogsport.steigert.tyrian;
1
2
import android.os.Bundle;
3
4
import com.badlogic.gdx.backends.android.AndroidApplication;
5
import com.blogspot.steigert.tyrian.Tyrian;
6
7
/**
* This class simply defines an Android activity for our game.
8
*/
9
public
class TyrianAndroidLauncher
10
extends
11
AndroidApplication
12
{
13
@Override
public void onCreate(
14
Bundle savedInstanceState )
15
{
16
super.onCreate( savedInstanceState );
17
18
// whether to use OpenGL ES 2.0
19
boolean useOpenGLES2 = false;
20

// create the game


21
initialize( new Tyrian(), useOpenGLES2 );
22
}
23
}
24
25
26
27
And when you execute it on an Android device you'll get:

Conclusion
We created the project structure for our game and tested it both on the desktop and on the
Android device. The next posts will focus on libgdx internals and how to use it to implement
the features of our cool game. A project was created on Google Code so that you can
easily browse the source code. I created a tag on the Subversion repository for this post's
project state. Let me know if I can improve/correct something, and I see you soon!

Game Screens
Libgdx version used on this post: 0.9.2 (download)

On the previous post we created our project structure on Eclipse, talked about the events
handled by our game and created some launchers for desktop and Android. The next step
is to plan the game screens we'll have and come up with a solution to implement them
inside our main game project (tyrian-game).

More about Tyrian


Tyrian was released in 1995 by Epic Games. In 2004 it was made a freeware, and since
2007 all its graphics are available under an open license. I suggest you play the game to
have a feel about it. The steps follow:
1.
Go to the OpenTyrian project page
2.
Download the latest Win32 OpenTyrian release build
3.
Download Tyrian 2.1
4.
Unpack both archives in the same directory
5.
Run opentyrian.exe
Great game, isn't it? Nostalgia aside, let's plan our screen flow.

Notes on the screen flow:

A splash screen is initially shown, then we move to the main menu screen.

The menu allows the player to start playing the game, look the hall of fame and
adjust some options.

The start-game screen allows the player to start a new game or resume a previous
saved game.

The profile screen allows the player to view his/her profile and manage the ship.

The level screen loads a level and allows the player to play it.

Implementing the screens


It would be nice to separate the code based on the screen. In order to achieve that in
libgdx, we could modify our game's main class (Tyrian) to extend com.badlogic.gdx.Game,
which in turn implements ApplicationListener. Don't forget to modify your event handling
methods to call super, now that we're extending a class rather than implementing an
interface. Doing that, we'll have support to use the com.badlogic.gdx.Screen interface,
which delegates the event handling methods to one specific screen at a time. Creating a
base Screen class might come handy, so the final picture looks like this:

I'm not proud of that circular dependency between Tyrian and the screens, but for the sake
of a tutorial I'll ignore this problem. The Tyrian class will also be in charge of creating
Screens and enabling them (remember: always one screen each time). Each Screen
instance will be in charge of rendering itself. This is a nice approach because each screen
has a limited scope, which facilitates the maintenance of the code. To complete this step
we should tell our game to initially show the splash screen, and that is a piece of cake:
?
public class Tyrian
1
extends
2
Game
3
{
4
public SplashScreen getSplashScreen()
5
{
6
return new SplashScreen( this );
}
7

8
@Override
9
public void create()
10
{
11
Gdx.app.log( Tyrian.LOG, "Creating game" );
12
fpsLogger = new FPSLogger();
13
setScreen( getSplashScreen() );
}
14
15
(...)
16
}
17
18
19
Now that we have a base Screen class (AbstractScreen), I'll do some refactoring. The
render() method of Tyrian will just call super.render() and output the FPS, and the render()
method of AbstractScreen will clear the screen with the color black.
?
1
public class Tyrian
2
extends
3
Game
4
{
5
@Override
6
public void render()
{
7
super.render();
8
9
// output the current FPS
10
fpsLogger.log();
11
}
12
13
(...)
14
}
15
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

public abstract class AbstractScreen


implements
Screen
{
@Override
public void render(
float delta )
{
// the following code clears the screen with the given RGB color (black)
Gdx.gl.glClearColor( 0f, 0f, 0f, 1f );
Gdx.gl.glClear( GL20.GL_COLOR_BUFFER_BIT );
}
(...)
}

The delta parameter on the Screen's render method


Did you notice that "delta" parameter? In case you're wondering its meaning, let's imagine
two scenarios. On the first scenario, the player has a very humble smartphone, which can
process only 10 frames per second (FPS) of our game. On the second scenario, a player
has a high-end quad core smartphone capable of processing 100 frames per second. In

order to define the same notion of time on both devices, you use the "delta" parameter in
your mathematical calculations. That ensures the high-end device of our second scenario
won't display the game 10 times faster than the first device, but just output more frames to
have a smoother game experience. We won't use that by now, but as it showed up I
wanted to give a heads up.

Adding an image to the splash screen


It would be really sad if by the second post of this tutorial all we had was an empty screen.
Browsing the web I found a very cool image we could use for our splash screen. Check it
out:

Sadly we cannot just throw that image on our resources folder the way it is. Libgdx (and
many other gaming frameworks) requires us to use images with dimensions in the power of
2 (that is: 256x256, 512x256, 1024x512 and so on). But there is more to it. This image can
contain more than one image, so what you really have is an image atlas. Later we tell
which part of this image atlas we want to draw.
Edit: there is a tool called TexturePacker that eases the job of creating image atlases. It
will be detailed in a future article.
I want the splash image to stretch to take all the space available. So I must ensure the
splash image's ratio has the same ratio of our game's window, which is 1.6 (remember that
our game window's dimension is set to 800x480, so 800/480 gives us
1.666666666666667). Using the GIMP image editor I worked the image out to make its
ratio 1.6 and came up with the following image atlas of 512x512:

So far so good. The next step is to throw this image atlas in our resources folder, which is:
tyrian-android/assets. As the resources folder of tyrian-game is a link to this folder,
Eclipse automatically shows this image under the tyrian-game project tree. Finally, we
modify our SplashScreen class to use this resource, as follows:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

package com.blogspot.steigert.tyrian.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.blogspot.steigert.tyrian.Tyrian;
public class SplashScreen
extends
AbstractScreen
{
private Texture splashTexture;
private TextureRegion splashTextureRegion;
public SplashScreen(
Tyrian game )
{
super( game );
}
@Override
public void show()
{
super.show();
// load the splash image and create the texture region
splashTexture = new Texture( "splash.png" );
// we set the linear texture filter to improve the stretching
splashTexture.setFilter( TextureFilter.Linear, TextureFilter.Linear );
// in the image atlas, our splash image begins at (0,0) at the
// upper-left corner and has a dimension of 512x301
splashTextureRegion = new TextureRegion( splashTexture, 0, 0, 512, 301 );
}

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

@Override
public void render(
float delta )
{
super.render( delta );
// we use the SpriteBatch to draw 2D textures (it is defined in our base
// class: AbstractScreen)
batch.begin();
// we tell the batch to draw the region starting at (0,0) of the
// lower-left corner with the size of the screen
batch.draw( splashTextureRegion, 0, 0, Gdx.graphics.getWidth(),
Gdx.graphics.getHeight() );
// the end method does the drawing
batch.end();
}
@Override
public void dispose()
{
super.dispose();
splashTexture.dispose();
}
}

When we execute the desktop launcher, the following window is displayed:

Conclusions
We improved our main game project to support screens, each with its own well-defined
scope. We refactored the code a bit and changed the SplashScreen to actually show
something. And we realized that working with images is not that easy, but believe me, it
could be much harder. Libgdx does most of the work under the covers, so our screens can
focus on their jobs.
You can check-out/browse the resulting code on the Google Code web-site.
Thanks for reading!

scene2d
Libgdx version used on this post: 0.9.2 (download)

All we have by now is a splash screen that displays an static image. Wouldn't it be nice to
add some fading effect on this image? Things like these improve the user experience a lot,
so soon we'll deal with that. As we build our graphical user interface, we need to handle
things like selecting options, clicking on buttons, giving focus to an input widget and so on
so forth. Can you imagine doing that with images inside image atlases? You're lucky today.
There is a very cool feature of libgdx called scene2d that basically provides useful
abstractions for rendering 2D components. Let's understand it better!
As of libgdx 0.9.6 some of the classes used on this post were modified or removed. You
may want to read the post #13 after reading this post, which covers those changes.

About scene2d
Scene2d is a module of libgdx that eases the management and rendering of 2D
components, which are called Actors. These actors live on a tree structure inside a
container called Stage. They keep track of many rendering attributes, such as position
relative to the parent, color, visibility, dimensions, scale and rotation factors and more. They
are also responsible for hit detection.
Examples of actors would be: buttons, text fields, images, enemy targets, coins, the ship
we'll fly, shots and so on. We'll use scene2d a lot in our game. Also, it's possible to apply
actions on the actors, like translate, rotate, scale and fade actions. If needed, you can also
write your own action, but we'll get to that later.
I'll try and summarize the main concepts of scene2d below:

Actor - A 2D component that knows how to draw itself.

Group - An actor that contains other actors.

Stage - An engine that requests the actors to be drawn and handles user
interaction by distributing touch events to the actors.

Action - A function that modifies the actors' properties over time.


The following UML diagram shows it graphically:

Using scene2d
The first thing to do is setup a Stage where the actors will act. A nice place for it to live is
within a screen (each screen with its own stage). These are the steps for managing the
stage in our game:
1.
Create a Stage instance on the constructor of AbstractScreen class
2.
Resize its viewport when the screen is resized
3.
Call the Stage's act and draw methods within the screen's render method
4.
Dispose the stage within the screen's dispose method
For further details, please have a look at the source code of the AbstractScreen class.
Now, everything we have to do is add actors to the stage. Our actors should override
methods like act() and draw(), which are automatically invoked by the stage on the
appropriate time.

Modifying the Splash screen


We want the splash image to be an actor so that we can do cool things with it. Instead of
extending
the
Actor
class,
we
can
just
use
the
Image

(com.badlogic.gdx.scenes.scene2d.ui.Image) actor that comes with scene2d. We still have


to load the texture and the texture region. We should also tell the image how to be drawn,
and that it should take all the screen size. Have a look at the source code for the modified
SplashScreen class to see how it's done.
Regarding that "actions" object inside SplashScreen.resize(), that's the coolest thing we
can do with scene2d. Each actor can be animated by actions. What we do with our splash
image is to add a set of the following actions:
1.
Fade-in in 0.75 seconds
2.
Wait for 1.75 seconds
3.
Fade-out in 0.75 seconds
We want also to move on to the next screen when the action is completed, so all we have
to do is add a completion listener to the "actions" object. Note that we didn't need to
override the screen's render method on the splash screen, because the splash image is an
actor that was added to the stage, and the stage is the one in charge of rendering it.

More about actions


The three actions we used on the splash image ship with libgdx. That is:

Fade-in action: com.badlogic.gdx.scenes.scene2d.actions.FadeIn

Fade-out action: com.badlogic.gdx.scenes.scene2d.actions.FadeOut

Delay action: com.badlogic.gdx.scenes.scene2d.actions.Delay


I suggest you take some time to check all the available actions inside the
packagecom.badlogic.gdx.scenes.scene2d.actions, but basically there are two types of
them:

Concrete actions - Actions that modifies the actors directly (FadeIn, FadeOut,
MoveBy, RotateBy, ScaleTo, etc).

Support actions - Actions that group or organize other actions in specific ways
(Delay, Sequence, Parallel, Repeat, Forever, etc).
Every action comes with a factory method named "$" that takes the required parameters for
it to work properly. If you want to create a FadeIn action that lasts 2 seconds, you can just
write:
?
FadeIn fadeInAction = FadeIn.$(2f);
1
The delay action has a different factory method. The following code creates the FadeOut
action 5 seconds delayed.
?
1
FadeOut fadeOutAction = FadeOut.$(2f);
Delay delayAction = Delay.$(fadeOutAction, 5f);
2
In order to have the complete effect we want, we need to join both actions:
?
Sequence sAction = Sequence.$(fadeInAction, delayAction);
1
And finally, add the action to the actor:
?
actor.action(sAction);
1
Piece of cake, isn't it? The last thing about actions I should not forget, is that you can also
add interpolators to them. That means your action can start slow and them accelerate
gradually, for instance. Interpolators define the rate of change for a given animation. In
libgdx they also come with the "$" factory method, so you can easily create them.

Domain model

A domain model describes the entities, their attributes, roles and relationships for a given
domain of interest. Most of our business logic will stay on the domain entities, because in
software engineering it's a nice idea to isolate the business logic. It makes the code
straightforward to other programmers, and even to ourselves later on. It also helps when
switching technologies. Say we want to switch from 2D to 3D graphics. If the business logic
is isolated, the impact of this change will be kept to a minimum.
With the help of scene2d we can achieve this objective rather easy, as each of the
drawable domain entities can map to a scene2d actor. That's how we'll separate the
business code from the presentation code. So the next task for us is to define our domain
model. In order to make it simple, we're not going to implement a full clone of Tyrian, but
just the main aspects of it. After analyzing the game for some time, I came up with the
following diagram:
You can check the complete source code for the domain model here.

Conclusion
This post was an introduction to scene2d. We saw how easy it is to use it, and how to
extend it with custom functionality. We added a fade effect to the splash image and now it
looks like a real splash image. Finally, we implemented the domain model for our game in
an isolatted manner. The tag for this post on the Subversion is here. Thanks for reading!

TableLayout
Libgdx version used on this post: 0.9.2 (download)

It's time to start coding our great menu screen. Before digging into it, let's have a look at
some important changes I made to the source code.
As of libgdx 0.9.6 some of the classes used on this post were modified or removed. You
may want to read the post #13 after reading this post, which covers those changes.

Important changes

Updated the version of libgdx to the latest version available. All I had to do was
download the latest build and replace the JARs and .so files on both projects (tyrianandroid and tyrian-game). We should get used to this procedure.

Changes on AbstractScreen:

The collaborators (BitmapFont, SpriteBatch, Skin) are now lazily loaded.

The show() method redirects the input processing to our Stage object
through: Gdx.input.setInputProcessor( stage );

The hide() method calls dispose(), or the dispose() method would never be
called at all.

TWL - Themable Widget Library


Libgdx includes a library called TWL. This is the description copied from their official website: TWL is a graphical user interface library for Java built on top of OpenGL. It provides a
rich set of standard widgets including labels, edit fields, tables, popups, tooltips, frames and
a lot more. Different layout container are available to create even the most advanced user
interfaces.
When compared to libgdx's scene2d's UI abstractions, TWL is way more powerful. It
contains even an HTML renderer capable of processing CSS configuration. You can fully

customize your widgets using a tool called TWL Theme Editor (Java Web-Start link). For
the sake of simplicity we'll stick to scene2d, but in the future we can move up to TWL.
Some examples of TWL GUIs:

Creating the Menu Screen with scene2d


Using the TextButton (com.badlogic.gdx.scenes.scene2d.ui.TextButton) actor that comes
with libgdx we could create a simple menu screen with three buttons: "Start game",
"Options" and "Hall of Fame". Let's remember the screen flow published on a previous
post:

We'll use the following screen layout:

A welcome message should be displayed at the top.

The three buttons should appear sequentially.

All components should be vertically aligned on the center of the screen.


I know, a designer would be welcome here. But let's focus on the code. :)
The most straightforward way of implementing this would be to assign absolute values to
the (x,y) coordinates of each actor. If we did that, we'd come up with the following code:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

package com.blogspot.steigert.tyrian.screens;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.ClickListener;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.blogspot.steigert.tyrian.Tyrian;
public class MenuScreen
extends
AbstractScreen
{
// setup the dimensions of the menu buttons
private static final float BUTTON_WIDTH = 300f;
private static final float BUTTON_HEIGHT = 60f;
private static final float BUTTON_SPACING = 10f;
public MenuScreen(
Tyrian game )
{

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

super( game );
}
@Override
public void resize(
int width,
int height )
{
super.resize( width, height );
final float buttonX = ( width - BUTTON_WIDTH ) / 2;
float currentY = 280f;
// label "welcome"
Label welcomeLabel = new Label( "Welcome to Tyrian for Android!", getSkin() );
welcomeLabel.x = ( ( width - welcomeLabel.width ) / 2 );
welcomeLabel.y = ( currentY + 100 );
stage.addActor( welcomeLabel );
// button "start game"
TextButton startGameButton = new TextButton( "Start game", getSkin() );
startGameButton.x = buttonX;
startGameButton.y = currentY;
startGameButton.width = BUTTON_WIDTH;
startGameButton.height = BUTTON_HEIGHT;
stage.addActor( startGameButton );
// button "options"
TextButton optionsButton = new TextButton( "Options", getSkin() );
optionsButton.x = buttonX;
optionsButton.y = ( currentY -= BUTTON_HEIGHT + BUTTON_SPACING );
optionsButton.width = BUTTON_WIDTH;
optionsButton.height = BUTTON_HEIGHT;
stage.addActor( optionsButton );
// button "hall of fame"
TextButton hallOfFameButton = new TextButton( "Hall of Fame", getSkin() );
hallOfFameButton.x = buttonX;
hallOfFameButton.y = ( currentY -= BUTTON_HEIGHT + BUTTON_SPACING );
hallOfFameButton.width = BUTTON_WIDTH;
hallOfFameButton.height = BUTTON_HEIGHT;
stage.addActor( hallOfFameButton );
}
}

And the following result:

All right, it does the job. But is this code easy to read and maintain? It contains many
mathematical calculations just to come up with screen coordinates for a simple design.
Let's try something better.

Introducing the TabletLayout


We could use the TableLayout project, which: is a lightweight library for describing a
hierarchy of GUI widgets and laying them out using rows and columns. Assembling GUI
widgets in code is clumsy and obfuscates the widget hierarchy. TableLayout provides its
own simple and concise language for expressing the GUI. TableLayout cleanly describes
an entire object graph of GUI widgets, leaving the Java code clean and uncluttered.
That's exactly what we want, and these are the steps to follow:
1.
Open the TableLayout Editor application (Java Web-Start link).
2.
Write the layout we want following the editor's language.
3.
Save the layout descriptor to a text file inside our resources folder.
4.
On the MenuScreen class, load this layout descriptor and make final
configurations.
With the following layout descriptor:
?
1
debug
2
* spacing:10 padding:0 align:center
3
'Welcome to Tyrian for Android!' spacingBottom:20
4
--[startGameButton] width:300 height:60
5
--6
[optionsButton] width:300 height:60
7
--8
[hallOfFameButton] width:300 height:60
9
I got the following preview:

Now we should save this layout descriptor inside our resources folder. I saved it under:
tyrian-android/assets/layout-descriptors/menu-screen.txt
The final step is to modify our MenuScreen class to read this file, as follows:
?
1
2
3
4
5
6
7
8
9
10
11

package com.blogspot.steigert.tyrian.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.ClickListener;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.tablelayout.Table;
import com.badlogic.gdx.scenes.scene2d.ui.tablelayout.TableLayout;
import com.blogspot.steigert.tyrian.Tyrian;

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

public class MenuScreen


extends
AbstractScreen
{
public MenuScreen(
Tyrian game )
{
super( game );
}
@Override
public void resize(
int width,
int height )
{
super.resize( width, height );
// retrieve the skin (created on the AbstractScreen class)
Skin skin = super.getSkin();
// create the table actor
Table table = new Table( getSkin() );
table.width = width;
table.height = height;
// add the table to the stage and retrieve its layout
stage.addActor( table );
TableLayout layout = table.getTableLayout();
//
//
//
//

[edit] this section is not needed


register the label "welcome"
Label welcomeLabel = new Label( "Welcome to Tyrian for Android!", skin );
layout.register( "welcomeMessage", welcomeLabel );

// register the button "start game"


TextButton startGameButton = new TextButton( "Start game", skin );
startGameButton.setClickListener( new ClickListener() {
@Override
public void click(
Actor actor,
float x,
float y )
{
game.setScreen( game.getStartGameScreen() );
}
} );
layout.register( "startGameButton", startGameButton );
// register the button "options"
TextButton optionsButton = new TextButton( "Options", skin );
optionsButton.setClickListener( new ClickListener() {
@Override
public void click(
Actor actor,
float x,
float y )
{
game.setScreen( game.getOptionsScreen() );
}
} );
layout.register( "optionsButton", optionsButton );
// register the button "hall of fame"
TextButton hallOfFameButton = new TextButton( "Hall of Fame", skin );
hallOfFameButton.setClickListener( new ClickListener() {
@Override
public void click(
Actor actor,
float x,
float y )
{
game.setScreen( game.getHallOfFameScreen() );
}
} );
layout.register( "hallOfFameButton", hallOfFameButton );

// finally, parse the layout descriptor


layout.parse( Gdx.files.internal( "layout-descriptors/menu-screen.txt" ).readString() );
}
}

And that's it! All mathematical calculations are gone. I also set the listeners to the buttons,
so that they move the player to other screens. Note that I'm just adding the table to the
stage. The other actors are registered on the table's layout, using the same IDs contained
in the layout descriptor.

Conclusion
In this post we saw how to implement a screen layout separating the presentation (layout
descriptor) from the controller (MenuScreen) code using TableLayout. Now we can easily
read it and modify it when necessary. It took us some effort to learn a new component, but
this effort will certainly pay off as we create and maintain the other screens. I didn't detail
the Skin object we used because it's not so important at this moment, and I would need an
entire post for it. This is the tag on Subversion for this post. Thanks!

Files
Libgdx version used on this post: 0.9.2 (download)

Moving on with our game development, I decided to make a slight change of plans. Instead
of having a "Hall Of Fame" screen I think it would be easier to implement a "High Scores"
screen. Let's go through all the steps...

Important changes

Resources reorganization: by the time the game is finished we'll have many
resource files, so it's a good idea to organize them now. I created folders for each type of
resource we currently have. That is: skin, image-atlases and layout-descriptors.

Splash screen refactoring: A reader of this tutorial shared a tip on how to better
use the screen's show/resize methods. In case the screen is resized, our actors don't need
to be recreated, but just resized/repositioned. Here is a link containing the changes made
to theSplashScreen and AbstractScreen. Thanks xryz!

About the High Scores screen


Following the "design standards" of the Menu screen, the High Scores screen will display
the best scores on each of the three levels of the game and a button to go back to the main
menu. Using the TableLayout Editor, I ended up with this layout descriptor:
?

1
2
3
4
5
6
7
8
9
10

debug
* padding:8
|
| fill:x
--'High Scores' colspan:2 spacingBottom:20
--'Episode 1'
[episode1HighScore]
--'Episode 2'
[episode2HighScore]

11
12
13
14
15
16
17

--'Episode 3'
[episode3HighScore]
--[backButton] colspan:2 width:300 height:60 spacingTop:30

And this preview:

Note: We talked about the TableLayout in a previous post.


The code for the HighScores screen is pretty similar to the Menu screen, so I won't go into
details.

The Profile domain entity


We should now think where these high scores will come from. Looking at our domain
model, the Profile class seems to be a good candidate since it contains other attributes that
should also be persisted across game restarts, such as the "credits" available to the player
and the current level she/he is currently at. This is the only domain entity we'll persist to a
data store.
We can use a simple Map attribute for holding the current best scores, using level IDs as
the keys. Please have a look at the Profile class. The Level class was also changed to
include an ID attribute.

Handling preferences in libgdx


One data store available to us is the preferences mechanism. It can hold simple key-value
pairs and uses the SharedPreferences class on Android, and a flat file on Desktop. Have a
look at the source code for the libgdx's Preferences interface and check out the methods it
declares. This is an usage example:
?

1
2

Preferences prefs = Gdx.app.getPreferences( "profile" );


prefs.putInteger( "credits", 1000 );

We could do it using preferences. It's simple and effective. But let's think a little bit more.

Some day we might release an updated version of our game. The Profile class may
have changed, so we'd have to read the old preferences and updated them to the new
preferences format.

There is a chance of the user to try and manually edit this preferences file in order
to gain advantages in the game.

As we're just persisting the state of one domain entity, maybe it's easier to have its
whole state serialized and deserialized later on.

We could add support for multiple profiles in the future.


Given that, let's see a second data store option.
Edit: in the post #6 I wrote about the preferences mechanism.

Handling files in libgdx


The files module is another abstraction of libgdx. It lets you handle files the same way
whether you're running the game on Android or on the Desktop. In the source code
repository of libgdx we can also see some new backends, like GWT and iOS. So
abstractions are a nice thing to have.
These are the available file types in libgdx:
1.
Classpath: Read-only files that live in the root of the compiled classes.
2.
Internal: Read-only files found in the root of the application (in the case of a
Desktop), or inside the assets folder (on Android).
3.
External: Read/Write files located in the user's home directory (in the case
of a Desktop), or in the root of the SD Card (on Android).
4.
Absolute: Files referred to through absolute paths, which is normally not a
cool thing.
5.
Local: Read/Write files located in the game's root directory (in the case of a
Desktop), or in the private application folder (on Android). This file type was added
recently and is very interesting. The advantages of using it on Android is that: (1)
these files are private to the application, (2) in case the application is removed, so
are these files, (3) there is no availability problem (the SD Card is not always
available).
Like in Java, a directory is considered to be a File in libgdx, but instead of re-using the
java.io.File class, the com.badlogic.gdx.files.FileHandleclass is used (independent of
the file's type). The following lines show how to create a FileHandle for each of the
available file types:
1.
Gdx.files.classpath( "config.properties" );
2.
Gdx.files.internal( "data/config.properties" );
3.
Gdx.files.external( ".tyrian/game-progress.xml" );
4.
Gdx.files.absolute(
"/Users/gustavo.steigert/.tyrian/game-progress.xml" );
5.
Gdx.files.local( "data/game-progress.xml" );
Now that we know how to create file handles, the following list shows what we can do with
them:

Read: there are many read methods, but the simplest one is readString(), which
returns a String with the contents of the file.

Write: there are also many write methods. The simplest is writeString(content,
append/overwrite).

List: in case it points to a directory, calling list() retrieves an array of FileHandle


with the children.

Delete: erases the file with delete(), or the directory with deleteDirectory().

Copy/Move:
copies/moves
the
file/directory
with
copyTo(destination)/moveTo(destination).
In case some of these operations fail, a GdxRuntimeException will be thrown (which is a
RuntimeException).
Edit: this section was updated to cover the new file type "internal". In a next post we'll use
this new file type instead of "external".

Using the JSON format


When writing to a text file we'll use the JSON notation to model our data. If you don't know
JSON yet you should really take the time to read about it. JSON is gradually replacing XML
since its output is easier for humans and machines to read, and the output is not so
lengthy.
We'll make the Profile class know how to generate a JSON representation of its state, and
also how to recover it later on. The first thing to do is make the Profile class implement
com.badlogic.gdx.utils.Json.Serializable, which declares the following methods:
?

1
2
3
4

public interface Serializable {


void write (Json json);
void read (Json json, OrderedMap<String, Object> jsonData);
}

The Javadocs for the JSON classes in libgdx are missing, so reading the source code and
analysing other projects I came up with the following implementation in our Profile class:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

@SuppressWarnings( "unchecked" )
@Override
public void read(
Json json,
OrderedMap<String,Object> jsonData )
{
currentLevelId = json.readValue( "currentLevelId", Integer.class, jsonData );
credits = json.readValue( "credits", Integer.class, jsonData );
// libgdx handles the keys of JSON formatted HashMaps as Strings, but we
// want it to be integers instead (because the levelIds are integers)
Map<String,Integer> highScores = json.readValue( "highScores", HashMap.class,
Integer.class, jsonData );
for( String levelIdAsString : highScores.keySet() ) {
int levelId = Integer.valueOf( levelIdAsString );
Integer highScore = highScores.get( levelIdAsString);
this.highScores.put( levelId, highScore );
}
}
@Override
public void write(
Json json )
{
json.writeValue( "currentLevelId", currentLevelId );
json.writeValue( "credits", credits );
json.writeValue( "highScores", highScores );
}

The method calls are pretty intuitive. We're writing key-values in write() and recovering
them with the correct types in read(). These methods still lack the code for saving/restoring
the Ship's items. I think you can easily handle it, so I won't go into details.

The Profile service


The last piece of the puzzle is to create a service to coordinate the reading and writing of
the Profile's state. It should define the location of the target file and expose read/write
operations, also handling eventual unexpected states. These are the detailed requirements
for the Profile service:
1.
Retrieve Profile operation

The target file that will hold the state of the Profile class will be an external
file located at: .tyrian/profile-v1.json; The "-v1" suffix allows us to update the file
model when new versions of the game get installed.

If the target file does not exist, one should be created based on an empty
Profile state.

If the target file exists, it should be read and supplied to a fresh Profile
instance, so that it can restore its state.

The
content
of
the
file
will
be
encoded
with
the
com.badlogic.gdx.utils.Base64Coder utility of libgdx, making it harder for players
trying to edit it manually.

Should any problem occur while reading the file or restoring the Profile
state, a fresh new Profile should be created and retrieved to the caller.
2.
Persist Profile operation

Have the given Profile instance generate its own JSON representation.

Encode the outcome with libgdx's com.badlogic.gdx.utils.Base64Coder.

Write the result to the target file.


If the player opens the target file, something like this will be displayed:
?
1

e2N1cnJlbnRMZXZlbElkOjAsY3JlZGl0czowLGhpZ2hTY29yZXM6eyIwIjoxMDAwLCIxIjoyNDAwLCIyIjo1MjAwfX0=

Editing it will likely invalidate the structure, making the decode operation impossible. In this
case, we just create a new Profile and move on with life.
You can find the source code for the Profile class here. Going back to the HighScore
screen, it should now retrieve the Profile through the Profile service, and simply display the
high scores for each level. This is the resulting screen for all this hard work (amazing, isn't
it?):

Conclusion
When dealing with the High Scores screen (old Hall Of Fame screen) we learned how to
use files in libgdx. We went a bit further and talked about the other persistence mechanism
(preferences), did some basic encoding to the game progress data and played with some
JSON utility classes. This is the tag on the Subversion for this post. Thanks for reading!

Preferences
Libgdx version used on this post: 0.9.2 (download)

Our next target is the Options screen.

About the Options screen

Once again we'll implement a very simple screen with the following options:

Sound Effects (enabled/disabled)

Music (enabled/disabled)

Volume (0-100)
Using the TableLayout Editor I wrote the following layout descriptor:
?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

debug
* padding:8
--'Options' colspan:3 spacingBottom:20
--'Sound Effects'
[soundEffectsCheckbox] colspan:2 align:left
--'Music'
[musicCheckbox] colspan:2 align:left
--'Volume'
[volumeSlider] fill:x
[volumeValue] width:40
--[backButton] colspan:3 width:300 height:60 spacingTop:30

Now we should think where to save these values.

Preferences mechanism
It makes no sense to store these option values in our domain model. The Profile class
deals specifically with domain attributes that must be saved. Using files is a valid option,
but we can use something simpler: the preferences mechanism. We can add just key-value
pairs to it and we don't need to care on how and where this information is going to be
persisted. Seems enough.
The first thing we should do is implement a class that abstracts the access to the
preferences mechanism. The following class does the job:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

package com.blogspot.steigert.tyrian;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Preferences;
/**
* Handles the game preferences.
*/
public class TyrianPreferences
{
// constants
private static final String PREF_VOLUME = "volume";
private static final String PREF_MUSIC_ENABLED = "music.enabled";
private static final String PREF_SOUND_ENABLED = "sound.enabled";
private static final String PREFS_NAME = "tyrian";
public TyrianPreferences()
{
}
protected Preferences getPrefs()
{
return Gdx.app.getPreferences( PREFS_NAME );

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

}
public boolean isSoundEffectsEnabled()
{
return getPrefs().getBoolean( PREF_SOUND_ENABLED, true );
}
public void setSoundEffectsEnabled(
boolean soundEffectsEnabled )
{
getPrefs().putBoolean( PREF_SOUND_ENABLED, soundEffectsEnabled );
getPrefs().flush();
}
public boolean isMusicEnabled()
{
return getPrefs().getBoolean( PREF_MUSIC_ENABLED, true );
}
public void setMusicEnabled(
boolean musicEnabled )
{
getPrefs().putBoolean( PREF_MUSIC_ENABLED, musicEnabled );
getPrefs().flush();
}
public float getVolume()
{
return getPrefs().getFloat( PREF_VOLUME, 0.5f );
}
public void setVolume(
float volume )
{
getPrefs().putFloat( PREF_VOLUME, volume );
getPrefs().flush();
}
}

These are the codes I'd like you to notice:


1.
Gdx.app.getPreferences( PREFS_NAME );
2.
getPrefs().flush();
The first one creates the preferences object if needed, then retrieves it to the caller. In the
Desktop, this file would be saved under %USER_HOME%/.prefs/tyrian, but just when the
second command gets executed. We should always flush the preferences after modifying
them. On Android devices, the SharedPreferences class would be used, so all preferences
are managed by the built-in preferences mechanism.

Implementing the Options screen


Before implementing the Options screen we could modify our Tyrian class to hold an
instance of TyrianPreferences. Now we can finally code our screen. I won't paste the
source code here because it is a bit lengthy, so I ask you to see it here. This is what we're
doing:

Like the other screens we create the scene2d actors and register them in our
TableLayout. Now we're handling two new kinds of actors: CheckBox and Slider.

We register listeners on these actors so that we do something when their state gets
change. Basically we call our TyrianPreferences class, which abstracts the usage of the
preferences mechanism.
This is the resulting screen:

We don't need to know how the preferences are saved on the Desktop, but in case you're
curious about it, this is the preferences file created by libgdx:
?

1
2
3
4
5
6
7

<?xml version="1.0" encoding="UTF-8" standalone="no"?>


<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<entry key="music.enabled">true</entry>
<entry key="volume">0.5</entry>
<entry key="sound.enabled">true</entry>
</properties>

Conclusion
We created the Options screen using new actors (checkbox and slider) and made them
save preference values through an abstraction to the preferences mechanism. Note that we
don't manage any audio yet, but we'll do it soon. This is the tag for this post on Subversion.
Thanks for reading!

Texture Packer
Libgdx version used on this post: 0.9.2 (download)

In this post we will implement the last screen of the menu, the Start Game screen.
As of libgdx 0.9.6 some of the classes used on this post were modified or removed. You
may want to read the post #13 after reading this post, which covers those changes.

Important changes

Inside the pause method of our game (Tyrian#onPause) I'm now calling
ProfileService#persist. This causes the game progress to be saved to an external file as I
explained in a previous post. It's important to put this method call inside the pause method
because we don't know if the player is coming back to the game after this method is
executed.

I also added a flag to define the current runtime environment (development or


production). This way we can change the game's default functionality to ease its
development. One example of that is during the persistence of the game progress
(ProfileService#persist). If we're in development mode there is no need to encode the
output file, so we can easily open and edit it with a text editor. I also had to modify the code
that reads the game progress to check if its contents are encoded or not.

Many changes were made to the domain entities in order to facilitate its usage. I
suggest you browse each domain class using the source code browser.

About the Start Game screen


This screen will have the following roles:
1.
Enable the selection of the level to be played.
2.
Customize the ship.
3.
Display the credits available to the player.
I'm considering you read the previous posts, so I'll summarize the steps involved: create
the layout descriptor and write the screen's code that reads it and configures the widgets.
On this screen we used a new widget, the SelectBox. Like the other widgets, it allows us to
set a listener so that we get notified when the player change the selection. Inside this
listener we coordinate the operation to be executed, delegating most of the checks to the
domain objects.

OpenGL and Textures


The Start Game screen works nice, but it is definitely not fun to customize the ship using
only form widgets. We should at least show an image of the installed items. We've been
using images for some time (in the Splash screen) but we never got into much detail, so
let's understand them better.
In 1992 Silicon Graphics Inc. released OpenGL, an API that defines many abstractions
easing the work with different graphical hardware. One of these abstractions is texture
mapping. It basically states that for an image to be displayed it must come from a texture
currently bound to the GPU's memory. In order to improve performance, we can put
multiple images inside a texture and later we tell which region of this texture we want to
draw. If the image we want to show is inside another texture (other than the currently bound
texture), a texture switching must occur on the GPU before OpenGL can render it. We
should try to minimize this texture switching because it can cause us performance issues.
In libgdx we can reference a texture using the com.badlogic.gdx.graphics.Texture class.
Note that it's very important to dispose a texture if you're not going to using it, because the
Java object that points to it is just a pointer, and the actual resource may be consuming the
GPU's memory. The Garbage Collector doesn't know anything about the GPU, so make
sure you're always disposing the textures correctly.

Image Atlas
In the previous section we learned that in order to optimize performance we should put
multiple images inside the same texture (instead of creating one texture for each image).
To do so we create the so called "image atlas", carefully picking related images for it. If the
images are not related, we'll end up switching textures too many times at runtime, which is
exactly what we want to avoid.
For the Splash Screen we created an image atlas of one image. That's ok because the
image is large and we didn't need any other image for this screen. But when we start
developing the game screen, we'll have to handle several small images. We should keep
track of the dimension and location of each image inside the image atlas in order to create
our TextureRegion objects later on. We could have our designer handle this, but we don't
have one and event if we had, there is a better approach we can use.

Texture Packer
Libgdx provides a tool called TexturePacker that basically creates image atlases for us. All
we have to do is specify where our individual images are, and where to save the output
image atlases. If needed, we can also set several settings to customize the output. In order
to use it, I followed the following steps:
1.
On Eclipse, I added a new JAR to the tyrian-game's classpath: gdxtools.jar. You can find this JAR inside the libgdx build you downloaded, or
preferably at this link, if you're using the latest libgdx version.
2.
I created a directory to hold the individual images at: tyriangame/etc/images. This will be our input directory. Then, I created sub-directories
based on the screen the images will appear. The TexturePacker uses these subdirectories to group the images, that is, images inside different sub-directories will
never be placed on the same image atlas.
3.
I created the image files, which you can see here.
4.
I created the TyrianTexturePacker class, which calls the TexturePacker the
way we want. Basically, I told the TexturePacker to read the images from our input
directory and save the output image atlases to our resource folder. Please read the
comments inside the class for detailed information.
5.
I ran the TyrianTexturePacker class and refreshed my resources folder.

Texture Packer Configuration


Instead of going through each configuration option, I'll share a great link that details all the
configuration that can be done. Note that the image files may follow a special nomenclature
for setting specific configuration that applies only to the image itself. The underscore
character is used to separate these special settings, so don't use it when naming your
image files unless you want to use this feature.
As an example of that, I updated the Splash screen to also use an image atlas generated
by the Texture Packer. I renamed the splash image to: splash-image_l,l.png. The "l,l" part
tells that the linear texture filter should be used when loading the image in runtime.

Using image atlases


Finally, I'll show how to load the image atlases generated by the TexturePacker tool.
1.
I modified the AbstractScreen class to add a new TextureAtlas attribute. I
create an instance of it in a lazy manner, and dispose it in the dispose method.
2.
In order to create a TextureAtlas instance, I call:
?
1

atlas = new TextureAtlas( Gdx.files.internal( "image-atlases/pages-info" ) );

This "pages-info" file was generated by the TexturePacker, and it contains all the
information of the generated image atlases.
3.
When I want to load an image, all I have to do is call
getAtlas().findRegion(), passing in the name of the image file I want. This in turn
gives me an instance ofAtlasRegion, which extends TextureRegion (the class we
used previously in the Splash screen to load the splash image). Check out the
source code for the modified Start Game screen for more details.
4.
I modified the layout-descriptor to include the image placeholders for the
ship's items. And with the region object in hand I can just call Image#setRegion to
display the image I want.
This is the final screen:

Conclusion
We created the Start Game screen and learned more about OpenGL textures. We used the
TexturePacker tool of libgdx to automatically create image atlases for us, so we can focus
on the game's mechanics. I didn't detail the source code changes too much, but I'm sure
you can figure them out using the source code browser. Thanks!

Sound and Music


Libgdx version used on this post: 0.9.2 (download)

The last change before start implementing the Level screen is to add sound and music to
the menu.

Important changes

I updated the libgdx JARs and SO files to the latest available.


The TyrianPreferences is now called PreferencesManager and lives inside the
services package.

In the Tyrian class (our game class) the services are created inside #create().

In the AbstractScreen class I removed the disposal of the stage, since it was
crashing the game in some 64-bit machines. I'm trying to understand this problem in depth,
so I hope I can come up with a better solution in the future.

The ProfileService was renamed to ProfileManager, and now it uses a new file
type: local (instead of external). In Android it will resolve to a folder private to the
application in the local file system instead of the SD Card's root. This is good for three
reasons: (1) when the application is removed, so are these files; (2) the SD Card is not
always available; (3) the files are private to the application. In the Desktop it will resolve to
the game's root folder.

Sound and Music


The com.badlogic.gdx.Audio interface allows us to easily handle sound and music in libgdx,
and you can get a valid instance just by calling: Gdx.audio. When working with audio it's
important to know that:

All sound and music should be disposed when they're no longer needed.

Sound instances are fully loaded to the heap and can have up to 1 MB.

You create sound instances through: Gdx.audio.newSound(FileHandle)

Music instances are streamed and are paused/resumed automaticaly when the
game is paused/resumed.

You create music instances through: Gdx.audio.newMusic(FileHandle)

The supported formats for both sound and music are: WAV, MP3 and OGG.

The Sound and Music services


When dealing with basic audio the hard work lies on creating nice services to work with.
Given the directives above it would be nice to:

Create separated sound and music services.

The music service should allow just one music to be played at any given time.

The sound service should cache the loaded sounds in order to improve
performance by avoiding excessive IO reads. An LRU (Least Recently Used) cache would
do the job, since we want to avoid reloading the most played sounds. After searching for
some code on the web I came up with this reusable LRUCache class. I also added an
eviction listener so I can dispose the sounds correctly.

Both services should manage the loaded resources, disposing them when they're
no longer needed.

Both services may be turned on/off at any time, and they should respect the volume
setting.
Please have a look at the source code for the MusicManager and the SoundManager. I
tried to write a detailed Javadoc to ease their understanding. The Tyrian class holds
references to all of our services, so I've also modified it to include our audio services. And
let's not forget about the Options screen, where we can turn the audio on/off and adjust the
volume.

Tyrian resources
The real Tyrian was made freeware some years ago, so it's very easy to find resources of
the game on the web. I found some official sound tracks and sound effects using Google,
and edited them a bit with Audacity to reduce the file sizes. We could work with lightweight
MIDI files, but it's not that easy to do so because we have to create code that will run only
on Android, and code that will run only on the Desktop. Also, we would have to manage
them manually, so we're better off sticking to one of the supported formats.
As an example of using the audio module I modified the source code of all screens to play
a click sound when clicking on any button, and the Splash screen starts playing the menu
music when it's created.

Conclusion
We learned how to use the audio module of libgdx. In case you need advanced audio
features you should try the gdx-audio extension. This is the tag for this post on the
Subversion repository. On the next post we'll start to implement the game itself, so I guess
it will take a while to finish writing it. Thanks for reading!

Viewport
Libgdx version used on this post: 0.9.2 (download)

In this post we will start implementing the Levels screen by creating an actor for our ship.

Important changes

Refactorings:
Removed the preview image's attribute from the enumerated
itemsShipModel, FrontGun and Shield in favour of a methodItem#getSimpleName(). With
this method the advantage is that the ship's items don't contain any specific presentation
information anymore. That allows us to create a convention to name our image files.

Created the LevelManager in order to make the Level domain class


dumber.

Configurations:

Changed the tyrian-android project so that the activity prevents the screen
from dimming. This is as simple as adding a flag to the window (see
TyrianAndroidLauncher):
?
getWindow().addFlags( WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON );
1

Creating the ship's actor


With the help of scene2d we'll create the presentation object for our ship, namely
theShip2D actor. Instead of extending com.badlogic.gdx.scenes.scene2d.Actor we can
rather extend com.badlogic.gdx.scenes.scene2d.ui.Image, saving us many hours of
work. Its dimensions are automatically set based on the texture region's dimensions. These
are the requirements for the Ship2D actor:

The actor's image should be chosen based on the ShipModel of our ship.

On the desktop the keyboard should be used to control the ship. On Android, the
accelerometer should be used instead.

The ship should not be allowed to go off the screen.

When the ship moves horizontally it should tilt to the side it's moving.

The ship's acceleration/deceleration speed should start slow and increase


gradually.

Presenting the ship


The first thing to do is to create a new group of images containing each of our ship models,
which will be packed into an image atlas by the texture packer (for more details about this
tool please have a look at the post #7). Browsing the web I found this cool image atlas,
which I'll use to crop the images I want (highlighted in red):

Note that I just need the ship images tilting to the one side, because we can reuse these
images just by flipping them horizontally (e.g., by using a negative width). We'll have to
work with animations to tilt the ship, so I'll add an index to the image's name and later I'll be

able to retrieve an ordered collection of all the regions of a given image. Finally, I'll add
these images to tyrian-game\etc\images\level-screen, run the texture packer and refresh
my projects.
Now we can start implementing the Ship2D actor. I'll create it under the
packagecom.blogspot.steigert.tyrian.screens.scene2d. In order to ease its instantiation,
I'll add the following factory method:
?
1
2
3
4
5
6
7
8
9
10
11

/**
* Factory method to create a {@link Ship2D}.
*/
public static Ship2D create(
Ship ship,
TextureAtlas textureAtlas )
{
List<AtlasRegion> regions = textureAtlas.findRegions(
ship.getShipModel().getSimpleName() );
Ship2D ship2d = new Ship2D( ship, regions );
return ship2d;
}

Respecting our MVC architecture, Ship2D may know Ship but Ship may not know Ship2D.
So far, so good. In the Ship2D's constructor, all we need to do is the following:
?
1
2
3
4
5
6
7
8
9
10
11
12
13

/**
* Creates a new {@link Ship2D}.
*/
private Ship2D(
Ship ship,
List<AtlasRegion> regions )
{
// the super constructor does a lot of work
super( regions.get( 0 ) );
// set some basic attributes
this.touchable = false;
}

Finally we have to modify the Level screen to add our actor to the stage and center it
horizontally, similar to what we did on the other screens. You can view the complete source
code for the Level screen here. I also added a fade-in action to the whole stage (by
referencing the stage's root), because the real Tyrian also does it. When starting the
"Episode 1" level, we get the following screen:

Everything is working but the ship is too small, isn't it? We could create bigger images for
this screen, but I want to show you another approach.

Working with the stage's viewport


We've been using a fixed resolution for the game screen and we also resize the stage to
this resolution later on. But we know that Android devices may have different screen
resolutions, and sooner or later we'll have to deal with that, so let's go with sooner. What
we want to achieve is called resolution independence, and for that we have two options:
1.
Let the stage's dimension match the current resolution and show more or
less game objects as needed.
2.
Use a fixed resolution and stretch it to fit the current resolution.
In order to pick an option you have to analyze your game. Is it a problem to show more of
the game for devices with greater resolutions? Will that give an unfair advantage to some
players? Some games use an hybrid approach. They stretch the game without losing the
aspect ratio and then they fill in the blanks with something (generally by showing more of
the game).
We're going with the second option, as it is way easier than the first. But how can that
increase the size of our ship? Simply put, we could define a fixed dimension for our stage's
viewport in that the ship is not too small, and then we stretch the viewport to fill the current
screen resolution whatever it is. So far the viewport size matched the game window's size
(800x480), so if we want the ship to be two times bigger, we can set the viewport's
dimensions to 400x240 without losing the aspect ratio of 1.6 we had before.

Implementing the changes


In the AbstractScreen class we need to:

Define two constants for the fixed viewport dimensions:


?
protected static final int VIEWPORT_WIDTH = 400, VIEWPORT_HEIGHT = 240;
1

Modify the instantiation of the stage object to:


?
this.stage = new Stage( VIEWPORT_WIDTH, VIEWPORT_HEIGHT, true );
1

Remove the resizing of the stage from the resize method, as we don't care about
the current screen resolution anymore.
And finally we should:

Remove all the overrides of the AbstractScreen#resize method.

Set the dimensions of the actors that should fill the viewport within the show
method of each screen. For instance, in SplashScreen#show:
?
1
splashImage = new Image( splashRegion, Scaling.stretch );
splashImage.width = stage.width();
2
splashImage.height = stage.height();
3

Update the layout descriptors to better fit the smaller viewport. I'll use relative
dimensions on the layout descriptor, so if we change the fixed dimensions of the viewport
again there is a chance the layouts won't break. You can view the modified layout
descriptors here.
When I run the Desktop launcher on a 800x480 window I get the following screens:

The ship is now bigger, but the start game screen is now broken. We should refactor this
screen, creating other screens for each customizable item, but as we're playing with the
viewport, we could increase its dimensions just for the menu screens. So this is the plan:

All the menu screens should have a viewport of 800x480.

The level screen should have a viewport of 400x240.


You can browse the source code for the modified screens here. Now I suggest you play
with the game window's size, either by resizing it manually or using specific values on
TyrianDesktopLauncher. As you do that don't worry if the screen's contents are ugly. On
Android they look just nice.

Conclusion
We've finally started implementing the game by creating the Ship2D actor. We played with
the stage's viewport to increase the ship's size, and ended up discussing about how to

achieve resolution independence. In the next post we'll handle the ship's requirements not
yet implemented. Thanks for reading!

Accelerator and Keyboard


Libgdx version used on this post: 0.9.2 (download)

First of all, a big thanks to my first supporter! A german guy bought me a beer by donating
some money. Vielen Dank! Mit diesem Geld kaufe ich ein deutsches Weizenbier!

Important changes
Updated the ADT Plugin on Eclipse to version 17. It seems that every JAR that's inside the
"libs" folder of an Android project gets added to its classpath automatically. When testing I
also noticed that tyrian-game was not being sent to the Android device, so the game
crashed because of a ClassNotFoundException. This is what I did to fix the problems:
1.
In tyrian-android, I removed all the JARs from the classpath and let
Android reference them through the new Android Dependencies classpath item.
2.
Exported the "gdx.jar" item in Properties > Java Build Path > Order and
Exportof tyrian-game.
3.
Exported the tyrian-game item in Properties > Java Build Path > Order
and Export of tyrian-android.
More details about libgdx on ADT v17 can be found here.

Moving the ship


When rendering a screen (AbstractScreen#render method) we have to first process the
game logic and then draw the result. In the first part we can check for user input and modify
our actors accordingly. As we want to move the ship, a common approach is to use the
device's accelerometer as an input, but we should also support a keyboard because we're
testing the game on the Desktop.
We'll start by adding a moveShip(delta) method to Ship2D. This method will take care of
all the movement details, like making sure the ship is inside the screen, calculating its
variable movement speed and deciding whether to use a keyboard or the accelerometer.
Notice the method's delta parameter. With this information in hand we can define a
maximum movement speed for the ship whose unit is pixels per second. We could start off
setting some speed constant and adjusting it as needed. For instance:
?
private static final float MAX_MOVEMENT_SPEED = 250;
1
This means the ship can move 250 pixels per second. Our fixed game viewport is sized
400x240, so in practice the ship will take 400/250 (=1.6) seconds to fly from the left to the
right edges of the screen, and 240/250 (=0.96) seconds from the bottom to the upper
edges. We could go on with this approach, but let's say we change the fixed viewport's size
in the future in order to deliver higher resolution graphics. The movement speed would
need to be reviewed because of this. So instead, let's just use the time we want the ship to
travel between the edges of the screen.
?
private static final float MAX_HORIZONTAL_SPEED = (
1

AbstractScreen.GAME_VIEWPORT_WIDTH / 1.6f );
private static final float MAX_VERTICAL_SPEED = (
AbstractScreen.GAME_VIEWPORT_HEIGHT / 0.96f );

Later we can adjust these constants as we test the game on a real device.

Using the Keyboard


No secrets here. I'll just check if the arrow keys are pressed and move the ship accordingly.
?
if( Gdx.input.isKeyPressed( Input.Keys.UP ) ) y += (
1
MAX_VERTICAL_SPEED * delta );
2
else if( Gdx.input.isKeyPressed( Input.Keys.DOWN ) ) y -= (
3
MAX_VERTICAL_SPEED * delta );
4
if( Gdx.input.isKeyPressed( Input.Keys.LEFT ) ) x -= (
5
MAX_HORIZONTAL_SPEED * delta );
else if( Gdx.input.isKeyPressed( Input.Keys.RIGHT ) ) x += (
6
MAX_HORIZONTAL_SPEED * delta );
7

Using the accelerometer


We can check if an accelerometer is present with the following call:
?
Gdx.input.isPeripheralAvailable( Peripheral.Accelerometer )
1
With that we can decide which input mechanism to use. On Android we should not forget to
declare the accelerometer requirement on the AndroidManifest.xml. It is just informational,
but the app stores will use it to filter the supported applications for a given device.
?
1
<uses-feature
android:name="android.hardware.sensor.accelerometer"
2
android:required="true" />
3
And the following calls retrieve the accelerometer's current data:
?
1
2
3

Gdx.input.getAccelerometerX(); // points to the right (when in portrait orientation)


Gdx.input.getAccelerometerY(); // points upwards (when in portrait orientation)
Gdx.input.getAccelerometerZ(); // points to the front of the display (coming out of the screen)

Each retrieved value ranges from -10 to 10, but we should come up with specific ranges
that suit our game. In order to do that, I added the following code to the moveShip method:
?
1
if( Tyrian.DEV_MODE ) {
2
Gdx.app.debug( Tyrian.LOG,
3
Gdx.input.getAccelerometerX() + "," +
Gdx.input.getAccelerometerY() + "," +
4
Gdx.input.getAccelerometerZ() );
5
}
6
Then I executed the game on my device, decided the best ways to tilt the phone to move
the ship and noted down the values of the accelerometer. Notice that as the game is in
landscape mode, our game's x-axis corresponds to the accelerator's y-axis. Here they are:
Horizontal movement (accelerator's y-axis):

[-10,-2]: moving left at maximum speed

(-2,0): moving left at calculated speed

0: still

(0,2): moving right at calculated speed

[2,10]: moving right at maximum speed


Vertical movement (accelerator's x-axis):

[-10,0]: moving forward at maximum speed

(0,2): moving forward at calculated speed

2: still

(2,4): moving back at calculated speed


[4,10]: moving back at maximum speed
Given that, I can use the accelerometer's values to modify the ship's position on the stage:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

// x: 4 (back), 2 (still), 0 (forward)


// I'll translate the above values to (-2,0,2) so that my next calculations are simpler
float adjustedX = ( Gdx.input.getAccelerometerX() - 2f );
if( adjustedX < - 2f ) adjustedX = - 2f; else if( adjustedX > 2f ) adjustedX = 2f;
// y: -2 (left), 0 (still), 2 (right)
float adjustedY = Gdx.input.getAccelerometerY();
if( adjustedY < - 2f ) adjustedY = - 2f; else if( adjustedY > 2f ) adjustedY = 2f;
// since 2 is 100% of movement speed, let's calculate the final speed percentage
adjustedX /= 2;
adjustedY /= 2;
// notice the inverted axis because the game is displayed in landscape mode
x += ( adjustedY * MAX_HORIZONTAL_SPEED * delta );
y += ( - adjustedX * MAX_VERTICAL_SPEED * delta );

Making sure the ship is inside the screen


We don't want the ship to go off the screen, right? So all we have to do is check the ship's
position against the stage's dimensions. The following code does the job:
?
1
2

if( x < 0 ) x = 0; else if( x > stage.width() - width ) x = stage.width() - width;


if( y < 0 ) y = 0; else if( y > stage.height() - height ) y = stage.height() - height;

Notice that I used the ship's width and height because an actor's origin stays at the bottom
left corner.
You can view the complete source code for the Ship2D class here.

Conclusion
The ship is now able to fly, but there are still two problems to solve:
1.
The ship has no acceleration (it responds to commands immediately).
2.
The ship is not tilting to the side it's moving.
On the next post we'll handle that. Here is the Subversion repository tag for this post.
Thanks!

Vectors
Libgdx version used on this post: 0.9.3 (download)

Hi guys! I've been extremely busy with some parallel projects, but as I received some
donations and amazing feedbacks as well, I'll find some time to write more posts! In this
one we'll talk about vectors, an element that allows us to represent positions, speeds,
velocities, accelerations, directions, distances and so on.

Important changes

Updated the version of libgdx to the latest version available. All I had to do was to
download the latest build and replace the JARs and .so files in our projects.

Why should we use vectors?


Vectors are cool because they can represent some information in a way that's easy to
understand, handle and combine. Basically they represent a direction or a point within a
coordinate system, optionally with an associated scalar value.
So far we've dealt only with velocity, but we also want to add acceleration so that the ship's
movement seems more real. Using vectors we can easily calculate the final position of the
ship after both forces were applied just by combining them! If you want to study the vector
concept in depth you can check out this Wikipedia page.
With a vector in hands we can do the following operations:

Add/subtract other vector to/from it;

Multiply it by a scalar value;

Calculate its length, which gives us the associated scalar value;

Normalize it, which makes its length be 1;

Calculate its angle relative to the x-axis;

Rotate it by a given angle;

Calculate its distance to another vector.


Libgdx provides two vector implementations:

com.badlogic.gdx.math.Vector2 for 2D vectors (javadoc)

com.badlogic.gdx.math.Vector3 for 3D vectors (javadoc)


As you can see, they belong to the com.badlogic.gdx.math package, which is very useful.
It provides implementations of things like circles, planes, polygons, rectangles, spheres and
so on. I suggest you take some time to study this package in details. Maybe one day I'll
write about it.

Using a position vector


As an example, we will change our game to use a vector to represent the ship's position.
Let's start by modifying the Ship2D class to include the following vector attribute:
?
private Vector2 position; // unitless
1
Sadly the (x,y) position coordinates of an actor are not wrapped into a Vector2 object.
That's why we're using a position vector. At specific moments we'll have to update the
actor's position based on our position vector. Now we could rewrite ourShip2D#moveShip
method as follows (I omitted some code in favor of readability):
?

1
2
3
4
5
6
7
8
9
10
11
12
13
14

private void moveShip(


float delta )
{
// set the position vector to the ship's current position
position.set( x, y );
// move UP or DOWN
if( Gdx.input.isKeyPressed( Input.Keys.UP ) ) {
position.add( 0, MAX_VERTICAL_SPEED * delta );
} else if( Gdx.input.isKeyPressed( Input.Keys.DOWN ) ) {
position.sub( 0, MAX_VERTICAL_SPEED * delta );
}
// move LEFT or RIGHT
if( Gdx.input.isKeyPressed( Input.Keys.LEFT ) ) {
position.sub( MAX_HORIZONTAL_SPEED * delta, 0 );
} else if( Gdx.input.isKeyPressed( Input.Keys.RIGHT ) ) {

15
16
17
18
19
20
21
22
23
24

position.add( MAX_HORIZONTAL_SPEED * delta, 0 );


}
// update the ship's actual position
x = position.x;
y = position.y;
}

Using velocity and acceleration vectors


We're using vectors now, but the result was exactly the same as before! When we add the
acceleration vector we'll see all the magic happen. First, let's understand the difference
between speed, velocity and acceleration:

Speed is a scalar quantity that tells us how fast an object is moving; eg: 10m/s.

Velocity is a vector quantity that tells us how fast an object is moving and in what
direction; eg: 10m/s east.

Acceleration is a vector quantity that tells us the rate of change of velocity; eg:
10m/s south.
So what we need to do now is:
1.
Calculate the acceleration based on the user input.
2.
Modify the ship's velocity based on the calculated acceleration.
3.
Update the ship's position based on the modified velocity.
And we should enforce some rules:

The maximum acceleration will be 8px/s. When using the keyboard, this maximum
value is reached immediately, but when using the device's accelerator it should be
calculated.

The maximum speeds (horizontal and vertical) must be respected.

When reaching the boundaries, the ship's velocity should be zeroed, so that the
ship stops flying in the current direction.

Modifying the Ship2D#moveShip method


We need to set the maximum acceleration, just like we set the maximum speed:
?
private static final float MAX_ACCELERATION = 8; // unit: px/s
1
And we need the new vectors:
?
1
private Vector2 velocity; // unit: px/s
private Vector2 acceleration; // unit: px/s
2
Now, let's follow our plan:
1) Calculate the acceleration based on the user input
The acceleration should be set as follows:

User is pressing the left arrow key: acceleration.x = - MAX_ACCELERATION

User is pressing the right arrow key: acceleration.x = MAX_ACCELERATION

User is pressing the up arrow key: acceleration.y = MAX_ACCELERATION

User is pressing the down arrow key: acceleration.y = - MAX_ACCELERATION


We must not forget to adjust the value based on the current delta!

acceleration = acceleration * delta

2) Modify the ship's velocity based on the calculated acceleration


That's easy:

velocity = velocity + acceleration

check the max speed


3) Update the ship's position based on the modified velocity
That's easy too now that we have vectors:

position = position + velocity

check the boundaries

The result
Once again, I'll just detail the keyboard input here because it's simpler. Later you can check
out the full source code for the Ship2D class with detailed inline comments.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

private void moveShip( float delta )


{
// calculate the horizontal and vertical acceleration
acceleration.x = ( Gdx.input.isKeyPressed( Input.Keys.LEFT ) ? - MAX_ACCELERATION
: ( Gdx.input.isKeyPressed( Input.Keys.RIGHT ) ? MAX_ACCELERATION : 0 ) );
acceleration.y = ( Gdx.input.isKeyPressed( Input.Keys.UP ) ? MAX_ACCELERATION
: ( Gdx.input.isKeyPressed( Input.Keys.DOWN ) ? - MAX_ACCELERATION : 0 ) );
// note that when the keys are not pressed, the acceleration will be
// zero, so the ship's velocity won't be affected
// apply the delta on the acceleration
acceleration.mul( delta );
// modify the ship's velocity
velocity.add( acceleration );
// check the max speed
if( velocity.x < 0 ) {
velocity.x = Math.max(
} else if( velocity.x > 0 )
velocity.x = Math.min(
}
if( velocity.y < 0 ) {
velocity.y = Math.max(
} else if( velocity.y > 0 )
velocity.y = Math.min(
}

velocity.x, - MAX_HORIZONTAL_SPEED * delta );


{
velocity.x, MAX_HORIZONTAL_SPEED * delta );
velocity.y, - MAX_VERTICAL_SPEED * delta );
{
velocity.y, MAX_VERTICAL_SPEED * delta );

// update the ship's position


position.add( velocity );
// make sure the ship is inside the stage
if( position.x < 0 ) {
position.x = 0;
velocity.x = 0;
} else if( position.x > stage.width() - width ) {
position.x = stage.width() - width;
velocity.x = 0;
}
if( position.y < 0 ) {
position.y = 0;
velocity.y = 0;
} else if( position.y > stage.height() - height ) {
position.y = stage.height() - height;
velocity.y = 0;
}
// update the ship's actual position
x = position.x;
y = position.y;
}

52

Conclusion
We have implemented acceleration and the ship's behavior seems more real! Features like
these are absolutely necessary if we want the player to be able to immerse in the game. In
the next post the ship will tilt to the side its moving, and then we'll move on to another
actors!
Here is the Subversion repository tag for this post. Thanks!

2D Animations
Libgdx version used on this post: 0.9.4 (download)

Like in many other gaming frameworks, a 2D animation is just a sequence of static images
(frames) shown with a certain speed, creating an illusion of movement. On this post we'll
use an animation to make the ship tilt to the side it's moving.

Important changes made to the existing code:

Enabled the use of OpenGL ES 2.0 in the both launchers:TyrianAndroidLauncher


and TyrianDesktopLauncher. Libgdx will fallback to OpenGL ES 1.x in case the 2.0 isn't
available. This can bring your game some valuable performance enhancements as stated
here (section: Choosing an OpenGL API Version).

The Ship2D class was modified as follows:

We'll be using a simple MAX_SPEED constant (given in pixels/second),


instead of the previous MAX_HORIZONTAL_SPEED and MAX_VERTICAL_SPEED.

The moveShip method was simplified regarding its interpretation of the


accelerometer values. I also created a VectorUtils class to remove many ifs from this
method, making it easier to read.

A deceleration was added to make the ship stop flying when there is no
user input. I won't go into details on this because on the previous post I wrote about
acceleration, so you should be able to easily understand this modification. If you have any
questions, just post it as a comment.

Using animations
In libgdx we use the com.badlogic.gdx.graphics.g2d.Animation class to perform 2D
animations. This class holds the animation's frames (in the form of
TextureRegioninstances) and sets the time each frame should be shown. This utility class
performs no drawing at all. After it's created, we'll make use of the following method:
?
public TextureRegion getKeyFrame(float stateTime, boolean looping)
1
This method retrieves the next frame to be drawn. Let's understand each parameter:

float stateTime: this is an accumulator value that represents the time elapsed
since the start of the animation. We should store this value somewhere and add the delta
time to it before calling the method.

boolean looping: whether the animation loops or stops at the last frame.
In order to create an Animation instance we must supply the TextureRegion instances and
the frame duration in seconds. As we're using the Texture Packer to create our image
atlases, we can use our TextureAtlas instance to easily find all the frames the compose an

animation just by calling textureAtlas.findRegions( "animation-name" ), which returns a


list of AtlasRegion instances, which extend TextureRegion.
Note: we talked about the Texture Packer and image atlases in a previous post.
You can test and tune the frame duration value or come up with some formula, like: 2.5 /
frameCount
That means the whole animation lasts 2.5 seconds. Here you can read more about
animations in libgdx if you want.

Scene 2D and animations


Scene 2D has no animation actor, but that's not a problem because we can just change our
image actor's region based on the TextureRegion returned by the Animation class. Simply
put, we can do something like this:
?
1
animationStateTime += delta;
TextureRegion frame = animation.getKeyFrame( animationStateTime, false );
2
setRegion( frame );
3

Creating the tilt animation


The Texture Packer created the following image atlas for us:

Notice that we just have the tilt animation to the left. Later we'll use a trick to inverse the
image horizontally, so the ship will be able to tilt to both sides. Let's define the new
animation related attributes:
?
1
/**
2
* The ship's tilt animation.
3
*/
4
private final Animation tiltAnimation;
5
/**
6
* The ship's tilt animation's state time.
7
*/
8
private float tiltAnimationStateTime;
9
In the constructor we create the tilt animation:
?
this.tiltAnimation = new Animation( 0.15f, tiltAnimationFrames );
1
But were these frames come from? In our factory method (Ship2D#create) we receive a
TextureAtlas instance. So inside the factory method we can just call:
?
1
2

List<AtlasRegion> regions = textureAtlas.findRegions( ship.getShipModel().getSimpleName() );


Ship2D ship2d = new Ship2D( ship, regions );

There is a small problem with this approach. Both the level screen and the start game
screen have images for the ship, and as we use a convention to name our images, the

retrieved regions contain the ship's image of the start game screen. This image is not a part
of the tilt animation. We could just rename the images in order to avoid this conflict (and
this is the best fix in my opinion), but there is a trick we can do. The Texture Packer stores
the image's index when it's part of an animation. If the index is less than zero it's just an
static image. The following code removes the undesired ship's image:
?
1
2
3
4
5
6
7

List<AtlasRegion> regions = textureAtlas.findRegions( ship.getShipModel().getSimpleName() );


Iterator<AtlasRegion> regionIterator = regions.iterator();
while( regionIterator.hasNext() ) {
if( regionIterator.next().index < 0 ) {
regionIterator.remove();
}
}

Tilting the ship based on user input


We're almost done. All we have to do now is analyze the user input and tilt the ship. We're
better off creating a specific method for that, so now our Ship2D#act method now looks
like this:
?
1
@Override
2
public void act( float delta )
3
{
super.act( delta );
4
moveShip( delta );
5
tiltShip( delta );
6
}
7
And now let's add the tiltShip method. Please analyze the code below and read the inline
comments:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

/**
* Tilts the ship to the direction its moving.
*/
private void tiltShip(
float delta )
{
// the animation's frame to be shown
TextureRegion frame;
// find the appropriate frame of the tilt animation to be drawn
if( velocity.x < 0 ) {
frame = tiltAnimation.getKeyFrame( tiltAnimationStateTime += delta, false );
if( frame.getRegionWidth() < 0 ) frame.flip( true, false );
} else if( velocity.x > 0 ) {
frame = tiltAnimation.getKeyFrame( tiltAnimationStateTime += delta, false );
if( frame.getRegionWidth() > 0 ) frame.flip( true, false );
} else {
tiltAnimationStateTime = 0;
frame = tiltAnimation.getKeyFrame( 0, false );
}
// there is no performance issues when setting the same frame multiple
// times as the current region (the call will be ignored in this case)
setRegion( frame );
}

Important aspects of the above method:

Based on the velocity vector we can tell if the ship is moving horizontally.

We always increment the tiltAnimationStateTime variable with the given delta


before requesting the next animation's frame to be drawn.

We flip the image horizontally when needed. A positive width means the image is
not inverted (it's being displayed as it is). A negative width means the image is inverted
horizontally.

If the ship is not moving horizontally we reset the tiltAnimationStateTime variable


and set the current frame to the first frame.
The following video shows the result:

Conclusion
The ship is now tilting to the side it's moving. We used some tricks to get this done, but the
code is still readable. :) This is the Subversion tag for this post, and this is the full source
code for the Ship2D class. Thanks for reading!

Libgdx refactoring (version 0.9.6)


Libgdx version used on this post: 0.9.6 (download)

As libgdx evolves we'll need to update our code base to make use of the latest
improvements. The following posts were published on the official libgdx blog:

scene2d updates

Table Layout updates

Texture Packer v2
On this post I'll detail the most important changes. The first thing we should do is download
the latest version of libgdx and replace the JAR and SO files in our projects. After doing
that you'll notice that many compile errors will appear.

Important changes in scene2d


Getters and setters added
Using getters and setters is a simple best practice as it improves the encapsulation of
behavior, but it could hinder the performance because these methods will be called several
times for each rendered frame. I suggest you keep an eye on the FPS output of your game.
For Tyrian it won't make a difference. If you'd like to read more about the advantages of
using getters and setters, have a look at this question at stackoverflow.
Actions system rewritten
It's now even easier to combine actions because they can operate on the same properties
of an actor. The syntax has also changed a bit, so instead of FadeIn.$(0.75f) we can
statically import the action and use fadeIn(0.75f). The actions you can statically import can
be found in com.badlogic.gdx.scenes.scene2d.actions.Actions.
Previously we did this in SplashScreen:
?
1
2

Sequence actions = Sequence.$( FadeIn.$( 0.75f ), Delay.$( FadeOut.$( 0.75f ), 1.75f ) );


splashImage.action( actions );

And now we do:


?
1

splashImage.addAction( sequence( fadeIn( 0.75f ), delay( 1.75f ), fadeOut( 0.75f ) ) );

Generic event system developed


Each actor has a list of capture and event listeners. Both listeners extend the
genericcom.badlogic.gdx.scenes.scene2d.EventListener. The capture listeners may
intercept the events before they're handled by the event listeners. During this capture
phase, the event is given to the root down to the target actor. If the event is not cancelled
by a capture listener, the normal phase kicks in and the event is given to the target actor up
to the stage's root. Given that, the following is possible:

Instead of querying the input mechanism to move our ship, we could just receive
the input events as they happen and modify our actor accordingly
(seecom.badlogic.gdx.scenes.scene2d.ActorListener). I didn't see any event related to the
accelerometer though, so let's stick to what we were doing;

We can also fire our own events. I'm glad to see this feature, otherwise I'm pretty
sure we'd have to implement it ourselves;

We can create a hierarchy of event listeners, possibly extending one of the shipped
listeners:

ActorListener: listens for input events, like keyDown/Up/Typed, enter/exit,


touchUp/Down and so on;

ChangeListener: listens for change events, that is, when something


changed in an actor;

ActorGestureListener: makes it easy to work with gesture events, like


pinch, zoom and fling.

We can reuse event listeners by adding them to different actors.


Actions and the new event system
I was expecting to receive events as the actions started/stoped on some actor, but sadly it
doesn't work that way. In order to switch from the SplashScreen to the MenuScreen, we
used to do something like this:
?
1
2
3
4
5
6
7

Sequence actions = Sequence.$( FadeIn.$( 0.75f ), Delay.$( FadeOut.$( 0.75f ), 1.75f ) );


actions.setCompletionListener( new OnActionCompleted() {
public void completed( Action action ) {
game.setScreen( new MenuScreen( game ) );
}
} );
splashImage.action( actions );

Now that OnActionCompleted was removed, we can do this little trick:


?
1
2
3
4
5
6
7
8

splashImage.addAction( sequence( fadeIn( 0.75f ), delay( 1.75f ), fadeOut( 0.75f ),


new Action() {
public boolean act( float delta ) {
game.setScreen( new MenuScreen( game ) );
return true; // returning true consumes the event
}
} )
);

The Drawable interface


An abstraction was created to handle objects that know how to draw
themselves:com.badlogic.gdx.scenes.scene2d.utils.Drawable. The following list shows all
the currently shipped drawables, but of course you can also write your own:

EmptyDrawable: A good drawable to extend if you're planning to write custom


drawables. Provides a rectangular drawable area but draws nothing.

NinePatchDrawable: Wraps a NinePatch, which provides dynamic image


stretching. You can create nine patches with Android's draw9patch tool;

TextureRegionDrawable: Wraps a TextureRegion, which is a rectangular area of a


Texture;

SpriteDrawable: Wraps a Sprite, which describes both a texture region, the


geometry where it will be drawn, and the color it will be drawn.
Animations and the new Drawable interface
Remember we use a 2D animation to tilt the ship? The utility class we used
(com.badlogic.gdx.graphics.g2d.Animation) still requires TextureRegions for the
animation's frames. The problem is that the modified Image actor now requires a Drawable,
and not a TextureRegion. So we'd better create a map whose keys are TextureRegions
and the values, Drawables. This way we can avoid instantiating Drawables on demand,
which would wake up the garbage collector sometimes, resulting in small freezes while
playing
the
game.
Have
a
look
at
the
modified
com.blogspot.steigert.tyrian.screens.scene2d.Ship2D code for detailed information.

Utility classes added


Utility classes are great, aren't they? This list highlights some of them:

Pool and Poolable: A pool of objects that can be reused to avoid allocation;

ReflectionPool: A customization of pool that uses reflection to build instances;

Timer: Schedules the execution of tasks in a platform independent manner;

Array: A resizable, ordered/unordered array of objects;

DelayedRemovalArray and SnapshotArray: Customizations of Array that handle


concurrent modification in specific ways;
I suggest you take some time to view all classes under com.badlogic.gdx.utils. They can
really save you hours of work.
Documentation is being rewritten
It already contains many useful information (check it out), but meanwhile I make millions of
dollars with this blog. Have you clicked the ad banner today? :)

The new TexturePacker


The TexturePacker was completely rewritten. It's now said to be much faster, easier to use
and most importantly, it packs images better. A new packing algorithm is being used,
theMAXRECTS, created by Jukka Jylnki. Here is the official documentation for the
updated version. From the related libgdx post:

Configuration: The underscore file name conventions are gone. File names can
still have a numeric index, it is simply any numbers at end of the file name, before the file
extension. To better control packing in various ways, a "pack.json" file can be placed in
each
input
directory.
This
contains
the
JSON
for
the
com.badlogic.gdx.tools.imagepacker.TexturePacker2$Settings object. Each directory
inherits all settings from the parent directory and any property set here will override those.

Nine patches: Files with ".9" before the file extension are considered a nine patch
file. The pixels around the edges are read and stripped off before packing the image. Once
again, you can create nine patches with Android's draw9patch tool. The split information is
stored in the pack file, enabling TextureAtlas to provide instances of NinePatch. The splits
in the TextureAtlas file format are optional, so existing pack files are still compatible.
In Tyrian we'll add the pack.json file in tyrian-game/etc/images, and this file will hold the
configuration values for the TexturePacker. You can play with some properties if you want
to customize the output. The only non-default values I used were the "filterMin" and
"filterMag", which I set to "Linear". I also removed the configuration directives from the raw
images' names (e.g.: splash-image_l,l.png is now splash-image.png). To run the
TexturePacker, we could execute the following command on the prompt:
java
-classpath
gdx.jar;gdx-tools.jar
com.badlogic.gdx.tools.imagepacker.TexturePacker2 inputDir outputDir
packFileName

But we can do it inside Eclipse by creating a Java launcher. I saved it under /tyriangame/TyrianTexturePacker2.launch, so you can open it with your Eclipse like so: Run >
Run Configurations... > Java Application > TyrianTexturePacker2.
That done we can use the TextureAtlas class like this:
?
1
2
3
4

TextureAtlas atlas = new TextureAtlas(Gdx.files.internal("image-atlases/pages.atlas"));


AtlasRegion region = atlas.findRegion("image-name");
Sprite sprite = atlas.createSprite("image-name");
NinePatch patch = atlas.createPatch("image-name");

Important changes in Table Layout


Remember our layout descriptors? Well, they're gone. The main argument for its removal
was that most of the time we "have to fallback to the code to manage the UI". As I see, the

controller (screen) will be even more coupled to the view. I'm sad with this change because
I like to have the layout structure in separate files, but let's follow the updatedTableLayout's
documentation and modify our code. Now we have to do something like this:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

// creates the table actor


Table table = new Table();
// 100% width and 100% height on the table (fills the stage)
table.setFillParent(true);
// add the table to the stage
stage.addActor(table);
// add the welcome message with a margin-bottom of 50 units
table.add( "Welcome to Tyrian for Android!" ).spaceBottom( 50 );
// move to the next row
table.row();
// add the start-game button sized 300x60 with a margin-bottom of 10 units
table.add( startGameButton ).size( 300f, 60f ).uniform().spaceBottom( 10 );
// move to the next row
table.row();
// add the options button in a cell similiar to the start-game button's cell
table.add( optionsButton ).uniform().fill().spaceBottom( 10 );
// move to the next row
table.row();
// add the high-scores button in a cell similiar to the start-game button's cell
table.add( highScoresButton ).uniform().fill();

I removed the layout descriptors and updated all the screens to comply with this new API,
and you can see the result below:

Splash Screen

Menu Screen

Start Game Screen

Options Screen

High Scores Screen

Conclusion
Libgdx is not yet mature, so we should expect future refactorings like this one. But it's
evolving quite fast and it already provides many features required for commercial game
projects. This is the tag on the Subversion repository for this post, and I these are the
commit differences from the previous revision.
Thanks for reading!

You might also like