How do I make TextButtons using LibGDX?

后端 未结 2 1306
长发绾君心
长发绾君心 2021-01-07 14:16

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 =          


        
2条回答
  •  醉话见心
    2021-01-07 14:45

    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 uiAtlas =
                new AssetDescriptor("ui/uiskin.pack", TextureAtlas.class);
        //The skin
        public static final AssetDescriptor uiSkin =
                new AssetDescriptor("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.

提交回复
热议问题