3
votes

I'm trying to figure out how to realize the HUD interface for my brand new game. I wanted to create it by using the scene2d.ui set of widgets because I've heard that it's more suitable for a responsive UI. So, I'm trying to create a simple HUD in which there's a score Label aligned at the top-right side of the screen and a pause Button placed on the top-left side of the screen.

Now... I'm using a root Table (as explained in the Table guide https://github.com/libgdx/libgdx/wiki/Table#quickstart) that fills the stage.

I wanted to create a custom class for handling all the hud interface such as:

public class Hud extends Table{

    private Label scoreLabel;
    private Button pauseButton;

    public Hud(){
      setFillParent(true);

      BitmapFont font = (BitmapFont)    MyGame.assetManager.get(Constants.COUNTERS_FONT_NAME);

      LabelStyle labelStyle = new LabelStyle(font,Color.WHITE);
      scoreLabel = new Label("score:0", labelStyle);

      add(scoreLabel).width(2).height(1);

   }
}

The issue I'm fighting with is the following: the text inside the Label does not stay inside the Label. I mean: activating the debug mode I can see the rectangle representing the Label with the correct dimensions...but the text is completely out of bounds and does not scale.

As you can see the font I use is a BitmapFont that is generated when the Game starts via the library FreeTypeFont...The font is then added to the AssetsManager of the game.

I post the code I use for adding the font generator to the assets manager:

    //Register the FreeTypeFontGeneratorLoader
    InternalFileHandleResolver resolver = new InternalFileHandleResolver();
    assetManager.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(resolver));
    assetManager.setLoader(BitmapFont.class, ".ttf", new FreetypeFontLoader(resolver));


    //Load fonts
    FreeTypeFontLoaderParameter countersFontParameters = new FreeTypeFontLoaderParameter();
    countersFontParameters.fontFileName = Constants.BASE_FONT_NAME;
    countersFontParameters.fontParameters.size = 45;
    countersFontParameters.fontParameters.borderColor = Color.BLACK;
    countersFontParameters.fontParameters.borderWidth = 1;

    assetManager.load(Constants.COUNTERS_FONT_NAME, BitmapFont.class, countersFontParameters);

As you can see I load just one BitmapFont with a size of 45 pixels.

I don't know what the problem is; I would like to try with a classic BitmapFont .fnt in order to see if the problem is in the way the BitmapFont is generated but I'd also like to keep the FreeTypeFont solution.

Thanks in advance,

Luca

P.S.

One thing about the Stage... it uses a ScalingViewport so the dimensions are not in pixels but in virtual units (because my Game uses Box2d and I need a common unit both for the rendering and the physic simulation).

2
I've tried with a BitmapFont generated by a .fnt file but nothing changes.Luca Marzi

2 Answers

3
votes

I'm pretty sure that Label will not respond on automatic scaling of the viewport until you will call label.setFontScale( theScale ) explicite.

The best idea here, in my opinion, will be to create another stage exclusively for a HUD so you will have your stage with ScalingViewport (I admit I've never used this one - isn't it better to use some Fill or aomething like this one?) and another stage with FitViewport above for example.

I find it very reasonable and intuitive since it will be like having your HUD displayed on yours car windscreen when driving the car.

The code should looks like:

    //in your show method
    viewport = createYourScalingViewport();     
    stage = new Stage();    

    stage.setViewport(viewport);

    HUDviewport = new FitViewport(screenWidth, screenHeight);
    HUDstage = new Stage();

    HUDstage.setViewport(HUDviewport);

    ...

    //adding some actor to stages
    stage.addActor(actor1);
    stage.addActor(actor2);

    //BUT
    HUDstage.addActor( yourHudInstance );

    ...

    //then in your render method act() and draw() stage then HUDstage so the HUD will be above stage
    stage.act();
    stage.draw();

    HUDstage.act();
    HUDstage.draw();

Remember of updateing HUDviewport in case of window resizing in the resize Screen method

0
votes

I guess I've solved my problem. It seems to be that it doesn't make sense to set the label dimensions.

If anyone needs to have a container that was tight to the text is rendered inside the label the best solution is to create a custom class like this below that extends an HorizonaltGroup (o VerticalGroup).

Let's imagine I need a score label for my game:

public class ScoreLabel extends HorizontalGroup{

 ...

}

Inside this class I create a Label property and I add it as an Actor.

public class ScoreLabel extends HorizontalGroup{

 private Label scores;
 public static final float FONT_SCALE = 0.9f;

 public ScoreLabel(){

    BitmapFont font = MyGame.assetManager.get(Constants.COUNTERS_FONT_NAME);
    LabelStyle labelStyle = new LabelStyle(font, Color.WHITE);
    scores = new Label(getScoreText(), labelStyle);
    scores.setAlignment(Align.left);
    scores.setFontScale(FONT_SCALE);   


    addActor(scores);
 }

}

If you activate the debug mode you'll notice that there's a container that is perfectly tight to the text is rendered. The code above simply loads a BitmapFont previously loaded inside the game assets manager. Then a font scale is applied...I guess it could be added inside a skin property Anyway...This is the best solution for me. I'm still using a stage with a ScalingViewport, in this way I have not to use pixels as unit and all the dimensions are scaled to fill the device screen.

Bye,

Luca