如何使用 LibGDX 制作 TextButtons?
我已经按照 youtube 上的一些教程为我的 libgdx 游戏制作按钮,但遇到了无法加载我的 button.pack 的问题.
stage = new Stage();black = new BitmapFont(Gdx.files.internal("font/black.fnt"));white = new BitmapFont(Gdx.files.internal("font/white.fnt"));atlas = new TextureAtlas(Gdx.files.internal("buttons/button.pack"));皮肤 = 新皮肤(图集);表 = 新表(皮肤);table.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());TextButtonStyle textButtonStyle = new TextButtonStyle();textButtonStyle.up = skin.getDrawable("buttons/buttonup.png");textButtonStyle.over = skin.getDrawable("buttons/buttonpressed.png");textButtonStyle.down = skin.getDrawable("buttons/buttonpressed.png");textButtonStyle.pressedOffsetX = 1;textButtonStyle.pressedOffsetY = -1;textButtonStyle.font = 黑色;buttonPlay = new TextButton("PLAY", textButtonStyle);buttonPlay.pad(20);table.add(buttonPlay);buttonHelp = new TextButton("HELP", textButtonStyle);buttonHelp.pad(20);table.add(buttonHelp);buttonExit = new TextButton("EXIT", textButtonStyle);buttonExit.pad(20);table.add(buttonExit);table.debug();stage.addActor(table);
所有按钮文件(buttonup.png、button.pack 等)都位于 my-game-gdx-core 下的资产文件夹中的按钮"文件夹中(参见链接).我无法编译并收到错误无法加载文件:buttons/button.pack.png"问题.请帮忙!
这里是错误链接:
然后我使用 TexturePacker 将所有 UI 图像打包在一起.这会生成一个图像表和一个看起来像这样但没有 split
参数的 txt 文件:
uiskin.png格式:RGBA8888过滤器:线性,线性重复:无容器蓝色旋转:假xy: 17, 2尺寸:41、45拆分:20、20、22、22原版:41、45偏移量:0, 0指数:-1集装箱黄金旋转:假xy: 60, 2尺寸:41、45拆分:20、20、22、22原版:41、45偏移量:0, 0指数:-1
分割参数旨在使这些图像正确拉伸.我曾经问过一个问题英雄,他们是如何工作的. 那又如何你要做的是在你的绘图应用中查找图像,看看哪些部分需要拉伸并填写分割参数.
精灵表和 txt 文件一起被称为 TextureAtlas
,一旦你创建了一个类似 TextureAtlas atlas = new TextureAtlas("uiskin.png");
的图集,你可以通过 atlas.findRegion("container_blue")
请求纹理,但是这是一个相当昂贵的调用,所以不要每次更新都这样做.
现在,对于真正的魔力,LibGDX 提供了一个皮肤,您可以在其中存储样式.皮肤文件为 .json
格式,如下所示:
<代码>{com.badlogic.gdx.graphics.g2d.BitmapFont:{默认值:{ 文件:字体/myDefaultFont.fnt }大:{ 文件:字体/myLargeFont.fnt }},com.badlogic.gdx.graphics.Color:{白色:{ a:1,r:1,g:1,b:1}绿色:{ a:1,r:0,g:1,b:0}灰色:{ a:1,r:0.5,g:0.5,b:0.5}黑色:{ a:1,r:0,g:0,b:0}},com.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle: {默认值:{ 字体:默认值,字体颜色:白色 }container_gold:{背景:container_gold,字体:默认,fontColor:绿色}},com.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle: {默认值:{ 字体:大,字体颜色:白色 }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 }},}
其实很简单.首先,我找到我的字体并命名它们,然后为我的字体添加一些颜色.从那里我为我的标签添加了两种样式,为我的 TextButtons 添加了 3 种样式.如果我将它加载到 Skin
这样的 Skin skin = new Skin("Gdx.files.internal("uiskin.json"), atlas);
我可以创建很多具有我使用单行创建的样式的按钮.
//这将使用默认字体创建一个更大的按钮.TextButton textButton = new TextButton("点击我!", skin, "container_gold");//这将创建一个较小的按钮TextButton textButton = new TextButton("点击我!", skin, "container_gold_small");//这将创建一个看起来与第一个按钮完全相同的标签标签 label = new Label("标签", skin, "container_gold");//这将使用默认样式绘制没有背景的较小的白色文本Label label = new Label("默认文本", skin);
提前做了一些工作,但效果很好.还有一件事,如果你有很多屏幕,你不应该每次都加载一个新皮肤.您应该使用 AssetManager
.这更容易设置,您只需要一个小班.我使用资产描述符加载资产,从而在需要查找皮肤或图集时节省了输入更多字符的时间.
公共类资产{//资产管理器公共静态 AssetManager manager = new AssetManager();//图集,我把.txt改名为pack(只是一个习惯).public static final AssetDescriptor<TextureAtlas>uiAtlas =new AssetDescriptor("ui/uiskin.pack", TextureAtlas.class);//皮肤public static final AssetDescriptor<Skin>uiSkin =new AssetDescriptor<Skin>("ui/uiskin.json", Skin.class,新的 SkinLoader.SkinParameter("ui/uiskin.pack"));//将资产加载到管理器的方法公共静态无效负载(){manager.load(uiAtlas);manager.load(uiSkin);}//简单的资产处置,只要你完成它只需处置管理器而不是许多文件.公共无效处置(){manager.dispose();}}
您可以使用启动屏幕和快速加载栏来使用它,但基本上您需要做的就是将以下代码作为运行的第一行代码.
//这是在我的第一个 `create()` 方法之上.//告诉管理器开始加载资产.load();//告诉程序循环"加载直到完成.从本质上阻止游戏继续进行.Assets.manager.finishLoading();
如果您发布游戏并且加载时间超过几秒钟,那么您最好使用某种启动/加载屏幕.
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 = new Stage();
black = new BitmapFont(Gdx.files.internal("font/black.fnt"));
white = new BitmapFont(Gdx.files.internal("font/white.fnt"));
atlas = new TextureAtlas(Gdx.files.internal("buttons/button.pack"));
skin = new Skin(atlas);
table = new Table(skin);
table.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
TextButtonStyle textButtonStyle = new TextButtonStyle();
textButtonStyle.up = skin.getDrawable("buttons/buttonup.png");
textButtonStyle.over = skin.getDrawable("buttons/buttonpressed.png");
textButtonStyle.down = skin.getDrawable("buttons/buttonpressed.png");
textButtonStyle.pressedOffsetX = 1;
textButtonStyle.pressedOffsetY = -1;
textButtonStyle.font = black;
buttonPlay = new TextButton("PLAY", textButtonStyle);
buttonPlay.pad(20);
table.add(buttonPlay);
buttonHelp = new TextButton("HELP", textButtonStyle);
buttonHelp.pad(20);
table.add(buttonHelp);
buttonExit = new TextButton("EXIT", textButtonStyle);
buttonExit.pad(20);
table.add(buttonExit);
table.debug();
stage.addActor(table);
all button files (buttonup.png, button.pack etc.) are in a 'buttons' folder which is in my assets folder under my-game-gdx-core (see link). I cannot compile and get the error 'Couldn't load file: buttons/button.pack.png' I don't know why it is looking for a png extension when i obviously just put buttons.pack, or if that is even the problem. Please help!
Here is a link to the error: https://gyazo.com/1ef8cce0b1935ad450d9f5229b0d698e
I don't see how it could be a problem with where the files are located because all other png's in assets can be loaded.
解决方案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.
相关文章