1
\$\begingroup\$

I want to add buttons to my libgdx based game and have them be independent of the window's size, but when I resize the window, the buttons stretch and deform instead of being resized and/or moved.

Most answers online say that this problem can be solved by resizing the stage's viewport, but I am already doing that and it confuses me, because I have no clue what the problem could be. To me it just looks like it is drawing to a texture that gets initialized to whatever size my window initially has, and is then stretched but never resized. Am I using it wrong? Or do I need to do something else?

What I start with:

initial buttons layout

What I end up with:

buttons after resizing the window

What I actually want (made with paint):

how I want it to look like

My code:

MainMenuScreen.java

public class MainMenuScreen implements Screen
{
    private Stage stage;
    private Table table;

    private MyGame game;

    public MainMenuScreen(MyGame game)
    {
        this.game = game;

        table = new Table();
        table.setFillParent(true);

        stage = new Stage();
        stage.addActor(table);

        Gdx.input.setInputProcessor(stage);

        // FIXME testing
        Skin skin = new Skin(Gdx.files.internal("skins/default/skin/uiskin.json"));
        
        TextButton button1 = new TextButton("Sandwich", skin);
        table.add(button1);

        TextButton button2 = new TextButton("Kebab", skin);
        table.add(button2);
    }

    @Override
    public void show()
    {

    }

    @Override
    public void render(float delta)
    {
        Gdx.gl.glClearColor(0, 0.2f, 0.3f, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        stage.act(delta);
        stage.draw();
    }

    @Override
    public void resize(int width, int height)
    {
        stage.getViewport().update(width, height, true);    
    }

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

MyGame.java

public class MyGame extends Game
{
    public SpriteBatch batch;
    public Input input;

    private MainMenuScreen mainMenuScreen;

    @Override
    public void create()
    {
        batch = new SpriteBatch();

        input = new Input();
        Gdx.input.setInputProcessor(input);

        mainMenuScreen = new MainMenuScreen(this);
        setScreen(mainMenuScreen);
    }

    @Override
    public void render()
    {
        super.render();
    }

    @Override
    public void dispose()
    {
        mainMenuScreen.dispose();
        batch.dispose();
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ Looks like you have the opposite issue of what is described here, maybe checking the difference between what they did and what you have could help? \$\endgroup\$
    – Vaillancourt
    Aug 24 at 16:01
  • 1
    \$\begingroup\$ Good catch, they are using a viewport which I am not, and adding one makes it work the desired way. \$\endgroup\$
    – happun
    Aug 24 at 19:27
1
\$\begingroup\$

It seems that a viewport is missing, as adding one yields the desired behaviour. The following code works for this purpose:

MainMenuScreen.java

public class MainMenuScreen implements Screen
{
    private Stage stage;
    private Table table;

    private OrthographicCamera camera;
    private FitViewport viewport;

    private MyGame game;

    public MainMenuScreen(MyGame game)
    {
        this.game = game;

        this.camera = new OrthographicCamera();
        this.viewport = new FitViewport(0, 0, camera);

        table = new Table();
        table.setFillParent(true);

        stage = new Stage();
        stage.setViewport(viewport);
        stage.addActor(table);

        Gdx.input.setInputProcessor(stage);

        // FIXME testing
        Skin skin = new Skin(Gdx.files.internal("skins/default/skin/uiskin.json"));
        
        TextButton button1 = new TextButton("Sandwich", skin);
        table.add(button1);

        TextButton button2 = new TextButton("Kebab", skin);
        table.add(button2);
    }

    @Override
    public void show()
    {

    }

    @Override
    public void render(float delta)
    {
        Gdx.gl.glClearColor(0, 0.2f, 0.3f, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        stage.act(delta);
        stage.draw();
    }

    @Override
    public void resize(int width, int height)
    {
        camera.setToOrtho(false, width, height);
        viewport.setWorldSize(width, height);
        stage.getViewport().update(width, height, true);   
    }

    @Override
    public void dispose()
    {
        stage.dispose();
    }
}
\$\endgroup\$

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.