Using libgdx with Texture Packer

downloadDownload the ready to use Eclipse project for this tutorial

One of the great challenges of game making is having your game work with good performances.

In the world of 2D game, you would think this shouldn’t be a problem considering the processing power of today’s CPUs. but the truth is, on a single threaded 2D game it is quite easy to reach the limit. And most likely, as an indie developer you won’t go for a complex architecture with say, a lot of threads and complex frustum culling. So you actually can quickly run out of power. A good start for optimization process is packing textures together.

Why using a texture packer?

Texture packing groups different textures on a single spritesheet. There are a few good reasons why you would want to do that:

  • Switching textures on OpenGL is a costly operation (glBindTexture)
  • Your quads can only reference UV mapping from a single texture. Switching texture means sending a quad to the GPU. Using the SpriteBatcher from libgdx, it means that the batch is flushed everytime you switch a texture. –that is a major performance hog
  • You only load one file and you’re done with it! –easier assets management
  • You save space: Texture Packer uses smart algorithms that will bundle all the images together in the best way possible

So performances of your app asides, packing your images into a single one is actually a lot easier to work with. It’s a win win situation so there’s no reason for you not to do it. Realizing this, the guy at libgdx packed the development framework with a built in texture packer able to work at run time. However, there is no reason you’d spend precious computation time doing this while you can perform this task beforehand. So we are going to use the tool Texture Packer, a free to use tool to do just that. Of course, you could as well pack all your textures neatly by hands using your favorite image editing tool, but that is an incredible waste of time. And believe me I actually did that with “Fireworks!”, carefully noting the coordinates of each image layer on Paint.NET. Let me tell you something: never again for the love of Internet would I do that again!

Texture Packer GUI

Texture Packer GUI

Example

Actions speak louder than words they say, so let’s try on a simple spreadsheet. The idea here is to pack an animation of 8 sprites of a skeleton walking, courtesy of Reiner’s Tilesets page:

Skeleton Walking

The 8 sprites we want to pack

With TexturePacker, all you have to do in order to pack these bad boys into a spreadsheet is to drag and drop the files, and tada! jobs done:

Default packing operated by TexturePacker

Default packing operated by TexturePacker

TexturePacker has automatically detected that the size of the spreadsheet to contain all these image should be 512×512 and they are all neatly arranged. Jobs done? Not so fast. TexturePacker comes in with plenty of configuration options, but one of them is especially useful: heuristic mask. This will detect that the brown color should actually be transparent and therefore pack your sprites even tighter:

Packign with heuristic mask

Packing with heuristic mask

There, a few clicks later, everything is packed into a 256×256 spreadsheet. The last thing to do now is to choose “LibGDX’ as dataformat and click on “Publish”. You can also save the texture packing project under a “tps” fileformat in case you want to add more sprites later on, but that is basically it.

Once done, you end up with two files: the spritesheet.png and a text file with the same filename:

Texture Packer generated files

The 2 files generated by Texture Packer and the tps project file (optional)

Now let’s see how to import this into LibGDX.

Using your spritesheet with LibGDX

Fire up a new libgdx project or import the one to download to your Eclipse and copy the spritesheet.png and .txt to your assets folder. Now, loading the spritesheet is very easy and is done with only one line of code:

spriteSheet = new TextureAtlas("assets/data/spritesheet.txt");

This will load the sprite sheet, but at this point is is useless. Now we need to retrieve the sprites from the sheet. There are two way to do this: createSprite or createSprites. By default TexturePacker will autodetect sprites of the same names and group them together. So for instance our files were named walkingse_0001.png, walkingse_0002.png etc. up until walkingse_0007.png, then TexturePacker grouped them together in a single entity walkingse.

This behavior is particularly useful to pack animations together. Now to create our sprites all we have to do is:

private Array<Sprite> skeleton;
skeleton = spriteSheet.createSprites("walkingse");

//dont forget to set the size of your sprites!
for(int i=0; i<skeleton.size; i++){
	skeleton.get(i).setSize(3.0f, 3.0f);
}

Creating the sprites don’t change their inital size and position, so you might want to change this.

And this is it! The render logic for this demo is just simply animating the skeleton by looping through the different frames of the sprites:

		//Game logic
		float dt = Gdx.graphics.getDeltaTime();
		animationElapsed += dt;
		while(animationElapsed > frameLength){
			animationElapsed -= frameLength;
			currentFrame = (currentFrame == skeleton.size - 1) ? 0 : ++currentFrame;
		}

		//render
		GL20 gl = Gdx.graphics.getGL20();
    	gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

		spriteBatch.setProjectionMatrix(cam2d.combined);
		spriteBatch.begin();
		skeleton.get(currentFrame).draw(spriteBatch);
		spriteBatch.end();

Watch the result below:

downloadDownload the ready to use Eclipse project for this tutorial

11 Comments

Leave a Reply

css.php