I will explain in this post why and how to use several layers on our maps. It’s a bit long post, so I will try to organize concepts in a clear way. If you have any doubt or suggestion, use the comments please and I will try to help you.
Introduction
On the previous article we see how to draw our map with libGDX. That case is very simple: a map with a single layer and a single tileset. It has a problem in order to work with it. See the image again to explain what the problem consists of:
Now supose the main character is walking on the scene. One of the things we have to do is to detect collides with the scene. A simple approach to do it could be to check whether the position the character is occupied by a tile or it’s empty. The problem of doing it with our example is that we have in the same layer the elements which the character would collide with (ground, water), and other decoration elements which wouldn’t collide with character (bush, house). So if we use this approach to detect collisions, the character will also collide with the decoration elements.
A solution to the posed issue is to split our scene in several layers: a main layer with the colliding elements, and as much layers as needed to decorate the scene.
Furthermore…
I have pointed the collision detection as the problem of using a single layer, but this has not be like this, because we can use another collision system (hardness map, physics engine, …). Nevertheless, other advantage we get using several layers better organization of our project resources or assets. We can have decoration tileset that we can use on several maps, although the main tileset of the scene changes, for example.
Next we will see how to use several layers and tilesets in our game scene maps.
Several tilesets
To continue with the example, I will create a second tileset, with tiles of 16×16 pixels, where I will draw som aditional decoration elements. This file is called decoration.png, and it’s stored on the same path of the map. This is the decoration.png tileset:
Modifying map
Next, we make the following changes on the map level.tmx:
- We have a first layer, called “terrain“, where are only the part of scenes which the characters collide with: ground and water. This layer uses the tileset tileset.png.
- In a second layer, called “background“, we set the house and bushes. This layer also uses the tileset tileset.png.
- At last, a third layer, called “decoration“, where we use the tileset decoration.png, and which contains some clouds and trees to decorate the scene.
This is the result after modifications:
Keep in mind
All used layers are “Tile layers“, that allows us to draw the scene from the tilesets.
As libGDX official doc says, we can use many layers as we need, but on each layer we only use one tileset. If not, the drawing performance will decrease a lot.
Crate a new project
To follow with the example, you can use the project we create on the previous article or you can create a new project. In my caso, I will clone the project using my cloning tool:
Handling layers in libGDX
libGDX give us functions to handle and draw whole maps, and also to do it for one or more isolated layers.
Getting layers
To get the layers of a map, we can use its name or its index of the layers list (first index is 0). The class that represents a layer created with Tiled Map Editor is TiledMapTileLayer
. In this example we will use these two methods.
The layer which contains the ground (“terrain“) will be stored in an TiledMapTileLayer
object, because this will be usefull to work with it in the future. On the other hand, for the rest of layers we use an array of integers called decorationLayersIndices
, where we set the indices of the layers “decoration” and “background“.
...
public class MyGdxTiledGame extends ApplicationAdapter {
...
private TiledMap map;
private TiledMapTileLayer terrainLayer;
private int[] decorationLayersIndices;
...
@Override
public void create () {
...
// Reading map layers
MapLayers mapLayers = map.getLayers();
terrainLayer = (TiledMapTileLayer) mapLayers.get("terrain");
decorationLayersIndices = new int[] {
mapLayers.getIndex("decoration"),
mapLayers.getIndex("background")
};
...
}
...
}
When working with layer’s indices, the order of the elements in the array matters. This is, the order in the array establishes the drawing order of the layers. In this caso, when the array decorationLayersIndices
is drawed, first is drawed the “decoration” layer and then the “background” layer over the first one.
Drawing layers
Layers drawing, same to map drawing, is made with an object of the class OrthogonalTiledMapRenderer
. See how to do it
public class MyGdxTiledGame extends ApplicationAdapter {
...
private OrthogonalTiledMapRenderer renderer;
...
@Override
public void create () {
...
// Instantiation of the render for the map object
renderer = new OrthogonalTiledMapRenderer(map);
}
@Override
public void render () {
// Clear screen
Gdx.gl.glClearColor(.5f, .7f, .9f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// Update the camera
camera.update();
renderer.setView(camera);
// Rendering
renderer.render(decorationLayersIndices);
renderer.getBatch().begin();
renderer.renderTileLayer(terrainLayer);
renderer.getBatch().end();
}
...
}
Important
Seeing the method render()
of the example, we can see differences between draw a TiledMapTileLayer
object and draw layer using its indices. In case of the TiledMapTileLayer
object its needed to start the drawing batch before to draw, and end the batch at finish drawing.
At last, say that decoration layers are drawed before terrain layer so that the terrain layer is over the decoration.
Source code
You can get the example project from my GitHub repository.