0
\$\begingroup\$

I'm having problems with creating static HUD/buttons on the game screen. Currently my game has a character moving on the tiled map, with OrthographicCamera put on, everything works fine. I wanted to add button on the screen:

...
Stage stage;
ImageButton imageButton;

@Override
public void create() {
        stage = new Stage(viewport);
        Texture texture = new Texture("bagbutton.png");
        Drawable drawable = new TextureRegionDrawable(new TextureRegion(texture));
        imageButton = new ImageButton(drawable);
        imageButton.setPosition(200, 200);
        imageButton.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent inputEvent, float x, float y) {
                System.out.println("clicked");
            }
        });

        Gdx.input.setInputProcessor(stage);
        stage.addActor(imageButton);
}
...

And then in render() method I got

stage.draw();

button appears, indeed, and it's even clickable. However, my player image (drawn by spritebatch.draw with texture) disappeared. Moreover, button is in the same position on map, and I'd like it to be somewhere on the bottom of the screen. It should be there statically, too, always in the same place, so when players moves, the button is always in the same place on screen. Next I'd like to make the same thing with some text and image, let's say on the top of screen. How to make it so?

\$\endgroup\$
  • \$\begingroup\$ You should create a new viewport for the hud/gui and render to that instead of the same viewport/camera as your game world. \$\endgroup\$ – Madmenyo Sep 6 '18 at 6:16
0
\$\begingroup\$

You should use different viewports for your hud and your player.
Make a Hud class for your Head-up display with the stage and the viewport:

public class Hud {

    private Stage stage;
    private FitViewport stageViewport;

    public Hud(SpriteBatch spriteBatch) {
        stageViewport = new FitViewport(500,500);
        stage = new Stage(stageViewport, spriteBatch); //create stage with the stageViewport and the SpriteBatch given in Constructor

        Table table = new Table();
        ...
        ... //add the Buttons etc.

        stage.addActor(table);
    }

    public Stage getStage() { return stage; }

    public void dispose(){
        stage.dispose();
    }
}

And then in your GameScreen, you can create an instance of Hud:

public class GameScreen implements Screen {

    private Hud hud;
    private SpriteBatch spriteBatch;
    private OrthographicCamera camera;
    private FitViewport playerViewport;

    public GameScreen() {
        spriteBatch = new SpriteBatch();
        hud = a new Hud(spriteBatch); //SpriteBatch eats a lot of memory so you can use the spriteBatch for both drawing the hud and the player

        //our camera and viewport for the player
        camera = new OrthographicCamera();
        playerViewport = new FitViewport(WORLD_WIDTH, WORLD_HEIGHT, camera);

        ... //other stuff like create the player etc.
    }

    @Override
    public void render(float delta) {

        Gdx.gl.glClearColor(0,0,0,1); //clear the screen
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        camera.update(); //update camera

        //First draw the player
        spriteBatch.setProjectionMatrix(camera.combined); //set the spriteBatch to draw what our playerViewport sees
        spriteBatch.begin();
        ... //draw player and game objects
        spriteBatch.end();

        //Secondly draw the Hud
        spriteBatch.setProjectionMatrix(hud.getStage().getCamera().combined); //set the spriteBatch to draw what our stageViewport sees
        hud.getStage().act(delta); //act the Hud
        hud.getStage().draw(); //draw the Hud
    }

    @Override
    public void resize(int width, int height) {
        playerViewport.update(width, height); //update our viewports
        hud.getStage().getViewport().update(width, height);
    }

    @Override
    public void dispose() {
        hud.dispose(); //dispose our hud
        spriteBatch.dispose(); //dispose the spriteBatch
    }

    ... //other methods for Screen pause(), resume(), hide()
}
\$\endgroup\$
  • \$\begingroup\$ Thanks, it works perfectly! I just wonder if I should add buttons to the table or directly to the stage. So far I have used table.add(imageButton).expand().bottom().right(); and it works fine, but maybe there's some general principle? \$\endgroup\$ – spectral Sep 6 '18 at 10:21
  • \$\begingroup\$ I would add the buttons to the Table because Tables offer many tools for handling the position and size of their children. \$\endgroup\$ – Morchul Sep 6 '18 at 10:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.