Tuesday, April 2, 2013

Libgdx Scene2d Skin quick tutorial

This post shows a brief introduction to using Skins in your Scene2d project. It's very useful to use a JSON file that declares all the styles for your Scene2d elements, but it can be counter-intuitive at the beginning.

  • First, create a skin.json file in your asset folder.
  • Create a couple BitmapFonts using Hiero. Let's say you create "arial25" for text and "impact50" for titles. Put the .fnt and .png files inside your asset folder. 
  • At this point, you can already start writing stuff in your skin.json file. You got the BitmapFonts ready, so you can define styles for the Label elements. For the colors you can specify the single RGB values (as float in the 0-1 interval) or you can use the hexadecimal notation. If you use hexadecimal, make sure the value is wrapped in double quotes so the parser always reads it as string.
   {  
     com.badlogic.gdx.graphics.g2d.BitmapFont: {  
      normaltext: { file: arial25.fnt },  
      titletext: { file: impact50.fnt },  
     },  
     com.badlogic.gdx.graphics.Color: {  
      red: { a: 1, b: 0, g: 0, r: 1 },  
      green: { a: 1, b: 0, g: 1, r: 0 },  
      blue: { a: 1, b: 1, g: 0, r: 0 },  
      white: { hex: "FFFFFF" },  
      black: { hex: "000000" } 
     },  
     com.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle: {  
      default: { font: normaltext, fontColor: white },  
      normal-text: { font: normaltext, fontColor: white },  
      title-text: { font: titletext, fontColor: red },  
     }  
   }  
  • Fire up GIMP or Photoshop and draw a square button, let's say 50x50. Put a gradient and a stroke on it so it looks nice. Save it as PNG in some external folder with the name "button.9.png". The ".9" piece at the end will tell the game that the button is a 9patch. More on that later.
  • Make another button, identical to the first, but in another color, for the "pressed" state. If you made the button blue, make it red or something. Save with the name "button-down.9.png".
  • Make another button, identical to the first, but gray, for the "disabled" state. Save with the name "button-disabled.9.png". 
  • Open your Android SDK folder and fire up the 9patch tool. You can find it in \sdk\tools\draw9patch.bat if you're on Windows. Open your buttons, and draw some black pixels in the middle of the top and left edges, to make it stretch gracefully. Save. You can find additional info on 9patches here and here
  • Use libgdx TexturePacker to create an atlas of your 3 buttons. Obviously you can pack them together with your other game graphics. Hint: you can also pack together your BitmapFont .png files generated at step 2. This way you can have a single texture for all your UI elements, so the rendering thread has to bind less textures each frame. More info about TexturePacker here.
  • Copy the created pack.atlas and pack.png in your asset folder.
  • Now you can define Button and TextButton styles in your skin.json file. It becomes something like this.
   {  
     com.badlogic.gdx.graphics.g2d.BitmapFont: {  
      normaltext: { file: arial25.fnt },  
      titletext: { file: impact50.fnt },  
     },  
     com.badlogic.gdx.graphics.Color: {  
      red: { a: 1, b: 0, g: 0, r: 1 },  
      green: { a: 1, b: 0, g: 1, r: 0 },  
      blue: { a: 1, b: 1, g: 0, r: 0 },  
      white: { hex: "FFFFFF" },  
      black: { hex: "000000" }  
     },  
     com.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle: {  
      default: { font: normaltext, fontColor: white },  
      normal-text: { font: normaltext, fontColor: white },  
      title-text: { font: titletext, fontColor: red },  
     }  
     com.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle: {  
      default: { up: button, down: button-down, checked: button-down, disabled: button-disabled },  
      transparent: { },  
     },  
     com.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle: {  
      default: { up: button, down: button-down, checked: button-down, disabled: button-disabled, font: normaltext, fontColor: white },  
     }  
   }  
  • Repeat the previous steps for creating more graphics for other Scene2d controls you want to style with your skin (like sliders, scrollbars, etc). But Labels and TextButtons are enough to get you started.
  • In your ApplicationListener.create() method, or whenever you load your assets, initialize the skin.
   AssetManager manager = new AssetManager();  
   ...  
   manager.load("pack.atlas", TextureAtlas.class);  
   ...  
   TextureAtlas atlas = manager.get("pack.atlas", TextureAtlas.class);  
   Skin skin = new Skin(Gdx.files.internal("skin.json"), atlas);  
  • That's it. Now you can create Labels, Buttons and TextButtons in your game, using your styles.
   Label label = new Label("Speed: 50m/s", Assets.skin); // Assets.skin is a static reference to the skin object 
   Label label = new Label("Speed: 50m/s", Assets.skin, "normal-text"); // equivalent to the previous label 
   Label label = new Label("Character selection", Assets.skin, "title-text");  

   Button buttonAttack = new Button(Assets.skin, "transparent"); // invisible button  
   TextButton buttonStart = new TextButton("Click to play!", Assets.skin);  

   Table table = new Table(Assets.skin); // this way you can enable table.add(String s)  
   table.add("First row", "title-text");  
   table.row();  
   table.add("Second row");  

More references about skins:

3 comments: