Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Java

How to Create a Default Skin to Use in Scene2D for Libgdx

5.00/5 (1 vote)
25 Sep 2017CPOL6 min read 7.7K  
How to create a default skin to use in Scene2D for Libgdx

When I first started out with Scene2d for UI work in Libgdx, I was introduced to the concept of skins. It seemed like a really convenient way for me to define how my UI elements look like.

Scene2d comes with a series of pre-defined Widgets. Widgets you can think of as the UI elements that you would use in your game, but with Scene2d, you get some extra features such as hierarchy organization and easier animations with them.

Some Widgets are:

  • Buttons
  • Labels
  • ImageButton
  • Image
  • TextButton

Now you might notice by looking at the documentation of these actors and their constructor and you might see that all, if not most of them require a Skin object to be passed in or at least set before you can render the button.

What are Skins?

Skins are a very convenient class that is used to store image resources such as textures, fonts, and more for your Scene2d Actors. It’s what defines what your UI elements will look like.

If you look at the documentation, you can see that you can store all of your assets into your Skin with a TextureAtlas and from there, you can pass it to your widget and from there, it’ll take care of everything for you.

What’s a TextureAtlas? How does Libgdx make the appropriate matching from a TextureAtlas to the appropriate widget types? All good questions!

When I first started out, I literally had no clue how to use Skins, how to make them, and then how to use them for my widgets. Here’s a quick rundown of everything I wish I knew when I started.

Disclaimer: There are multiple ways of using skins. I’m just showing you one way. This way might not be the simplest, but should be performance-wise.

How to Make a Skin

There will be 3 key files that you’ll need to have:

  • A .png file of all of your images combined into one .png file
  • A .atlas file to create the mapping (position and size) of your chosen images in your .png
  • A .json file to map the images you mapped in the .atlas file to the widget types in Scene2D

Unfortunately, Libgdx does not come pre-packaged with its own default skin, so you’re left to yourself to figure out how you can create a skin for the common UI elements. Luckily, Libgdx has a repository that has a large number of examples you can take from. Let’s take a look, shall we?

Specifically, let’s look at the default skin.

If you noticed, inside the default skin folder, we have 2 more folders, a raw and a skin folder. The raw folder contains numerous individual images and inside the skin folder, you’ll see the 3 specific files that I mentioned above. Let’s look at them.

The PNG File

If you look at uiskin.png, you’ll quickly see that it’s just an image with a lot of assets inside of it. The benefit of combining all of these assets together is so that there are less files to load, improving your game’s performance.

The Atlas File

Remember, an atlas file is a mapping of all our images that were packed together in our uiskin.png. If you look at uiskin.atlas, you’ll see.

It might look a bit scary at first, but let’s look at some of the lines that will be important to get started:

  • Line 2: The name of the packed png file that the atlas will be referring to
  • Line 3: The size of the PNG file
  • Line 7: If you look at the raw folder again, you’ll see that’s the name of one of the images
  • Line 9: The xy file location of the check-off image in our packed png file
  • Line 10: How large the check-off image is inside our packed png file

And that’s a high level of what we need to know to get to understand how .atlas file works.

Here’s a snippet code from the documentation showing how you can create a TextureAtlas and refer to specific parts of the image:

Java
TextureAtlas atlas;
atlas = new TextureAtlas(Gdx.files.internal("packedimages/pack.atlas"));
AtlasRegion region = atlas.findRegion("imagename");
Sprite sprite = atlas.createSprite("otherimagename");
NinePatch patch = atlas.createPatch("patchimagename");

With this, you can create a style for your widget and hand them off to your widget, something like this (also from the documentation).

Java
TextButtonStyle buttonStyle = skin.get("bigButton", TextButtonStyle.class);
TextButton button = new TextButton("Click me!", buttonStyle);

I’ll talk more in the future about how to pack your images together, but for now, you can refer to the TexturePacker documentation or see the GUI packer that I recommend to help you pack your files together.

The JSON File

At this point, you can stop and we would have accomplished our mission. We were able to take advantage of packaging images for better performance and a quick and easy way to create our UI.

Now, we’ll get to the final piece of using skins for your UI.

We’ll be creating a JSON file to help create a quick and easy way for us to use these assets without having to manually pair our assets with the specific styles we want to use.

I’ll be working under the assumption that you understand what a JSON object is, but if not, you should be able to pick it up as we go!

So looking at the example, we can see something like this:

Java
com.badlogic.gdx.graphics.g2d.BitmapFont: 
{ default-font: { file: default.fnt } },
	com.badlogic.gdx.graphics.Color: {
		green: { a: 1, b: 0, g: 1, r: 0 },
		white: { a: 1, b: 1, g: 1, r: 1 },
		red: { a: 1, b: 0, g: 0, r: 1 },
		black: { a: 1, b: 0, g: 0, r: 0 },
	},
	com.badlogic.gdx.scenes.scene2d.ui.Skin$TintedDrawable: {
		dialogDim: { name: white, color: { r: 0, g: 0, b: 0, a: 0.45 } },
	},
	com.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle: {
		default: { down: default-round-down, up: default-round },
		toggle: { down: default-round-down, checked: default-round-down, up: default-round }
	},
	com.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle: {
		default: { down: default-round-down, up: default-round, font: default-font, fontColor: white },
		toggle: { down: default-round-down, up: default-round, 
        checked: default-round-down, font: default-font, fontColor: white, downFontColor: red }

Each JSON object (or pair of {}), represent one of the styles for our UI widgets that we can use. I’d just grab a snippet, but you can find more examples in the example file or in the other skin files. Now the red might throw you off, but if you start reading it, this won’t seem as bad.

So let’s go look at the JSON object for Button:

Java
com.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle: {
	default: { down: default-round-down, up: default-round },
	toggle: { down: default-round-down, checked: default-round-down, up: default-round }
}

The key used in the object (com.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle) is used to represent the style that we want the UI to use.

Each of these Styles will allow you to create different types of styles, in this case, we have default and toggle.

Within our style tips, we define the image that we’ll use for each state of the button. For each style, you can find the supported states by looking at other examples or in the documentation. For this example, we can see that the values: down, checked, and up are used in the Button Style documentation.

For each of these keys, you can assign the name of the image you want to use for the file. If you look at the raw folder in the git repo or at your .atlas file, you’ll see the image names match the name of the values used in the JSON object.

All of these fields are optional, but if you don’t set any images in the JSON object for a style, nothing will happen.

Putting it All Together

Now at this point, I hope you have an understanding of all the files that are involved in creating an easy Skin object that will take care of the UI widgets for us.

The next and final part is a short sample code on how to use it.

Java
Skin skin = new Skin(Gdx.files.internal("uiskin.json"));
Button button = new Button(skin);
TextButton textButton = new TextButton("this uses a skin!", skin);

And that’s about all you need to do to use a skin. Just make sure to add your widgets to your stage so that the widgets will appear!

I hope this has been a useful article explaining how to use skins and get started with a demo skin to try creating your UI.

The post How to Create a Default Skin to use in Scene2D for Libgdx appeared first on Coding Chronicles.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)