I\'ve followed a few tutorials on youtube to make buttons for my libgdx game and have run into a problem where my button.pack cannot be loaded.
stage =
The first line of you .pack file refers to the bitmap connected to atlas. I'm pretty sure that what is there is
button.pack.png
instead of
button.png
Just edit it and this one should be alright.
But there's one more problem I see - you use scene2d which is very good and skin instance which is very good too - but why having skin you are creating TextButtonStyle from basics?
In my opinion you should create your TextButtonStyle using skin mechanism. You can read about it and see some example (even with TextButton) here:
http://www.gamefromscratch.com/post/2013/12/18/LibGDX-Tutorial-9-Scene2D-Part-3-UI-Skins.aspx
You most probably have to put your images in the android/assets
folder. The way you are creating your buttons looks fine however it LibGDX offers a much more convenient way of creating buttons with a bit of work in advance. This is how I create my buttons:
First I create an images like these:
I then pack all my UI images together using TexturePacker. This generates a image sheet and a txt file that looks something like this but without the split
parameters:
uiskin.png
format: RGBA8888
filter: Linear,Linear
repeat: none
container_blue
rotate: false
xy: 17, 2
size: 41, 45
split: 20, 20, 22, 22
orig: 41, 45
offset: 0, 0
index: -1
container_gold
rotate: false
xy: 60, 2
size: 41, 45
split: 20, 20, 22, 22
orig: 41, 45
offset: 0, 0
index: -1
The split parameters are designed to make those images stretch correctly. I once asked a question hero on SO how they work. So what you do is look up the image in your drawing app and see what portions need to be stretched and fill in the split parameters.
The sprite sheet and txt file together are called a TextureAtlas
and once you create an atlas like that TextureAtlas atlas = new TextureAtlas("uiskin.png");
you can ask for a texture by doing atlas.findRegion("container_blue")
however this is a rather expensive call so don't do this each update.
Now for the real magic LibGDX provides a skin where you can store Styles. A skin file is in .json
format and looks like this:
{
com.badlogic.gdx.graphics.g2d.BitmapFont: {
default: { file: fonts/myDefaultFont.fnt }
large: { file: fonts/myLargeFont.fnt }
},
com.badlogic.gdx.graphics.Color: {
white: { a: 1, r: 1, g: 1, b: 1 }
green: { a: 1, r: 0, g: 1, b: 0 }
gray: { a: 1, r: 0.5, g: 0.5, b: 0.5 }
black: { a: 1, r: 0, g:0, b:0 }
},
com.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle: {
default: { font: default, fontColor: white }
container_gold: { background: container_gold, font: default, fontColor: green }
},
com.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle: {
default: { font: large, fontColor: white }
container_gold: { down: container_gold, up: container_blue, disabled: container_grey, font: large, fontColor: green }
container_gold_small: { down: container_gold, up: container_blue, disabled: container_grey, font: default, fontColor: green }
},
}
It's actually very simple. First I locate my fonts and name them, then I add some colors for my fonts. From there I add two styles for my labels and 3 styles for my TextButtons. If I load this into a Skin
like this Skin skin = new Skin("Gdx.files.internal("uiskin.json"), atlas);
I can create many buttons with the styles I created using a single line.
//This would create a "larger button using the default font.
TextButton textButton = new TextButton("Click Me!", skin, "container_gold");
//This would create a smaller button
TextButton textButton = new TextButton("Click Me!", skin, "container_gold_small");
//This would create a label looking exactly like the first button
Label label = new Label("Label", skin, "container_gold");
//This would draw smaller white text without a background using the default style
Label label = new Label("Default text", skin);
It's a bit more work in advance but this works very well. One more thing though, if you have many screens you should not be loading a new skin each time. You should use a AssetManager
. This is even easier to setup all you need is a small class. I load my assets using a asset descriptor, saving me typing even more characters when I need to lookup my skin or atlas.
public class Assets {
//The asset manager
public static AssetManager manager = new AssetManager();
//The atlas, I renamed .txt to pack (just a habit).
public static final AssetDescriptor<TextureAtlas> uiAtlas =
new AssetDescriptor<TextureAtlas>("ui/uiskin.pack", TextureAtlas.class);
//The skin
public static final AssetDescriptor<Skin> uiSkin =
new AssetDescriptor<Skin>("ui/uiskin.json", Skin.class,
new SkinLoader.SkinParameter("ui/uiskin.pack"));
//Method for loading the assets into the manager
public static void load()
{
manager.load(uiAtlas);
manager.load(uiSkin);
}
//Easy asset disposing, whenever you are done with it just dispose the manager instead of many files.
public void dispose()
{
manager.dispose();
}
}
You can use this using a splash screen and a fency loading bar but essentially all you need to do is putting the following as the first lines of code to run.
//This is on top of my first `create()` method.
//Tell the manager to start loading
Assets.load();
//Tell the program to "loop" the loading until finished. Essentially stopping the game from continuing.
Assets.manager.finishLoading();
If you are releasing you game and loading takes more then a couple of seconds then you will be better off using somekind of splash/loading screen.