Joshflux
Joshflux

Reputation: 141

libgdx buttons not clickable

I have a problem with my current libGDX project. The game starts with a main menu, where you can click on two buttons. After starting the game, you can pause it through Esc and get to the pause screen, which is very similar to the main menu. I don't know why, but the buttons in the pause screen are not clickable. Here is the code of the game screen with the problem:

public class GameScreen implements Screen{

    private Texture[] monsterTextures = {Assets.manager.get(("Ressources/DemonHunter.jpg"), Texture.class), Assets.manager.get(("Ressources/WingedDemon.jpg"), Texture.class),
                                        Assets.manager.get(("Ressources/Viking.jpg"), Texture.class), Assets.manager.get(("Ressources/DemonWarrior.jpg"), Texture.class)};
    private Image[] monsterImages = {new Image(monsterTextures[0]), new Image(monsterTextures[1]), new Image(monsterTextures[2]), new Image(monsterTextures[3])};
    private Stage gameStage = new Stage(), pauseStage = new Stage();
    private Table table = new Table();
    private Skin menuSkin = Assets.menuSkin;
    private TextButton buttonContinue = new TextButton("Continue", menuSkin),
                       buttonExit = new TextButton("Exit", menuSkin);
    private Label title = new Label ("Game", menuSkin);
    private int randomMonster;
    private int currentMonsterLife = 1 + (int)(Math.random() * ((5-1) + 1));

    public static final int GAME_CREATING = 0;
    public static final int GAME_RUNNING = 1;
    public static final int GAME_PAUSED = 2;
    private int gamestatus = 0;


    @Override
    public void show() {

        randomMonster = 0 + (int)(Math.random() * ((3-0) + 1));
        gameStage.addActor(monsterImages[randomMonster]);

    }

    public void newMonster() {
        monsterImages[randomMonster].remove();
        Gdx.gl.glClearColor(0,0,0,1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        randomMonster = 0 + (int)(Math.random() * ((3-0) + 1));
        currentMonsterLife = 1 + (int)(Math.random() * ((5-1) + 1));
        gameStage.addActor(monsterImages[randomMonster]);
    }

    @Override
    public void render(float delta) {

        if(Gdx.input.isKeyJustPressed(Keys.ESCAPE)) pauseGame();

        if(gamestatus == GAME_CREATING) {
            buttonContinue.addListener(new ClickListener(){
                public void clicked(InputEvent event, float x, float y) {
                    Gdx.gl.glClearColor(0,0,0,1);
                    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
                    gamestatus = GAME_RUNNING;
                }
            });
            buttonExit.addListener(new ClickListener(){
                public void clicked(InputEvent event, float x, float y) {
                    Gdx.app.exit();
                }
            });

            table.add(title).padBottom(40).row();
            table.add(buttonContinue).size(150, 60).padBottom(20).row();
            table.add(buttonExit).size(150, 60).padBottom(20).row();
            table.setFillParent(true);
            pauseStage.addActor(table);
            Gdx.input.setInputProcessor(pauseStage);
            Gdx.input.setInputProcessor(gameStage);

            gamestatus = GAME_RUNNING;
        }

        if(gamestatus == GAME_RUNNING) {
            Gdx.gl.glClearColor(0,0,0,1);
            Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
            gameStage.act();
            gameStage.draw();

            if(Gdx.input.justTouched())currentMonsterLife -= 1;
            if(currentMonsterLife == 0)newMonster();
        }


        if(gamestatus == GAME_PAUSED) {
            Gdx.gl.glClearColor(0, 0, 0, 1);
            Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
            pauseStage.act();
            pauseStage.draw();
        }
    }



    public void pauseGame() {
        gamestatus = GAME_PAUSED;

    }

    @Override
    public void resize(int width, int height) {
        // TODO Auto-generated method stub

    }

    @Override
    public void pause() {
        pauseGame();

    }

    @Override
    public void resume() {
        // TODO Auto-generated method stub

    }

    @Override
    public void hide() {
        // TODO Auto-generated method stub

    }

    @Override
    public void dispose() {
        for(int i = 0; i < monsterTextures.length; i++) {
            monsterTextures[i].dispose();
        }
        gameStage.dispose();
        pauseStage.dispose();
        menuSkin.dispose();
    }

}

And here is the code of the main menu, where the buttons are working:

public class MainMenu implements Screen {

    private Stage stage = new Stage();
    private Table table = new Table();
    private Skin menuSkin = Assets.menuSkin;
    private TextButton buttonPlay = new TextButton("Play", menuSkin),
                       buttonExit = new TextButton("Exit", menuSkin);
    private Label title = new Label ("Hunt for Power", menuSkin);


    @Override
    public void render(float delta) {

        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        stage.act();
        stage.draw();

    }

    @Override
    public void show() {

        buttonPlay.addListener(new ClickListener(){
            public void clicked(InputEvent event, float x, float y) {
                ((Game)Gdx.app.getApplicationListener()).setScreen(new GameScreen());
            }
        });
        buttonExit.addListener(new ClickListener(){
            public void clicked(InputEvent event, float x, float y) {
                Gdx.app.exit();
            }
        });

        table.add(title).padBottom(40).row();
        table.add(buttonPlay).size(150, 60).padBottom(20).row();
        table.add(buttonExit).size(150, 60).padBottom(20).row();
        table.setFillParent(true);
        stage.addActor(table);
        Gdx.input.setInputProcessor(stage);

    }

    @Override
    public void resize(int width, int height) {
        // TODO Auto-generated method stub

    }

    @Override
    public void pause() {
        // TODO Auto-generated method stub

    }

    @Override
    public void resume() {
        // TODO Auto-generated method stub

    }

    @Override
    public void hide() {
        dispose();
    }

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

    }
}

I really hope someone is able to find the solution to this. Greetings, Joshflux

Upvotes: 1

Views: 1107

Answers (2)

Tenfour04
Tenfour04

Reputation: 93922

Like @donfuxx said, you should not set your input processor in the render() method, but rather in show().

And you can only set one input processor at a time. Your second call to setInputProcessor replaces the first call. If you want two different stages as input processors, you must combine them with an InputMultiplexer:

public void show(){
    Gdx.input.setInputProcessor(new InputMultiplexer(pauseStage, gameStage)); //list them in order of precedence
    //...your other code
}

Upvotes: 1

donfuxx
donfuxx

Reputation: 11321

There is something weird with how you set the InputProcessor:

in the show() method you set the Stage stage as the InputProcessor:

Gdx.input.setInputProcessor(stage);

so far so good, but in the render() method you set it to different stages than the one where your buttons are!

Gdx.input.setInputProcessor(pauseStage);
Gdx.input.setInputProcessor(gameStage);

==> remove this code from the render method! Also you should not have the other code that looks like it should only be executed when creating the screen inside the render() method. It seems like your code results in overlapping stages, buttons & tables and it is unclear which stage currently is set as InputProcessor.

Upvotes: 3

Related Questions