3
\$\begingroup\$

I have to classes which implements the Screen interface. I'm trying to switch between these screens. I'm able to switch one time, but when trying to switch back, I receive the error: AL lib: (EE) alc_cleanup: 1 device not closed

Here is the first screen class: public class GameOverScreen implements Screen { SpriteBatch batch = new SpriteBatch(); Stage stage = new Stage(); Image shipImg; Label gameOverLabel; TextButton mainMenuButton; TextButton exitButton; VerticalGroup group; Battleship battleshipGame; Skin skin; int width, height;

    public GameOverScreen(Battleship battleshipGame) {
        this.battleshipGame = battleshipGame;
        width = battleshipGame.width;
        height = battleshipGame.height;
    }

    @Override
    public void show() {
        Gdx.input.setInputProcessor(stage); // So that the stage can receive input-events like button-clicks
        skin = new Skin(Gdx.files.internal("android/assets/uiskin.json"),
                new TextureAtlas(Gdx.files.internal("android/assets/uiskin.atlas")));
        // Set up layout
        group = new VerticalGroup();
        group.setBounds(0, 0, width, height);
        group.space(15);
        group.pad(50);
        group.fill();

        // Create menu elements
        gameOverLabel = new Label("Game over!", skin, "default-font", Color.BLACK);
        // TODO: Show what player won the game
        gameOverLabel.setAlignment(Align.center);
        shipImg = new Image(new Texture("android/assets/battleship.jpg"));
        mainMenuButton = new TextButton("Go to Main Menu", skin);
        exitButton = new TextButton("Exit", skin);

        // Add them to menu group
        group.addActor(gameOverLabel);
        group.addActor(shipImg);
        group.addActor(mainMenuButton);
        group.addActor(exitButton);

        // Add scene to stage
        stage.addActor(group);

        // Create listeners
        mainMenuButton.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event,
                                float x,
                                float y) {
                //hide();
                //dispose();
                battleshipGame.setMainMenuScreen();
            }
        });
        exitButton.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event,
                                float x,
                                float y) {
                // TODO: EXIT GAME
            }
        });
    }
    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(1, 1, 1, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        batch.begin();
        stage.draw();
        batch.end();
    }

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

    @Override
    public void resize(int width, int height) {
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }

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

And the second:

public class MainMenuScreen implements Screen{
    SpriteBatch batch = new SpriteBatch();
    Stage stage = new Stage();
    Image shipImg;
    TextField nickNameField;
    String nickName;
    TextButton playButton;
    TextButton exitButton;
    Label nickNameLabel;
    VerticalGroup group;
    Battleship battleshipGame;
    Skin skin;
    int width, height;

    public MainMenuScreen(Battleship battleshipGame) {
        this.battleshipGame = battleshipGame;
        width = battleshipGame.width;
        height = battleshipGame.height;
    }

    @Override
    public void show() {
        Gdx.input.setInputProcessor(stage); // So that the stage can receive input-events like button-clicks
        skin = new Skin(Gdx.files.internal("android/assets/uiskin.json"),
                new TextureAtlas(Gdx.files.internal("android/assets/uiskin.atlas")));
        // Set up layout
        group = new VerticalGroup();
        group.setBounds(0, 0, width, height);
        group.space(15);
        group.pad(50);
        group.fill();

        // Create menu elements
        shipImg = new Image(new Texture(Gdx.files.internal("android/assets/battleship.jpg")));
        nickNameLabel = new Label("Enter nickname:", skin, "default-font", Color.BLACK);
        nickNameLabel.setAlignment(Align.center);
        nickNameField = new TextField("", skin);
        playButton = new TextButton("Find match", skin);
        exitButton = new TextButton("Exit", skin);

        // Add them to menu group
        group.addActor(shipImg);
        group.addActor(nickNameLabel);
        group.addActor(nickNameField);
        group.addActor(playButton);
        group.addActor(exitButton);

        // Add scene to stage
        stage.addActor(group);

        // Create listeners
        nickNameField.setTextFieldListener(new TextField.TextFieldListener() {
            @Override
            public void keyTyped(TextField textField, char key) {
                nickName = textField.getText();
            }
        });
        playButton.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event,
                                float x,
                                float y) {
                // TODO: FIND MATCH
            }
        });
        exitButton.addListener(new ClickListener() {
            @Override
            public void clicked(InputEvent event,
                                float x,
                                float y) {
                // TODO: EXIT GAME
                //Gdx.app.exit();
                // For testing:
                //dispose();
                battleshipGame.setGameOverScreen();
            }
        });

    }

    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(1, 1, 1, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        batch.begin();
        stage.draw();
        batch.end();
    }

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


    @Override
    public void resize(int width, int height) {
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }

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

As you can see, there is a button on each screen which calls setScreen(otherScreen) in the game.

Thanks!

\$\endgroup\$

closed as off-topic by Kromster says support Monica, bummzack, Anko, Seth Battin, congusbongus Mar 25 '15 at 0:18

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions about debugging a problem in your project must present a concise selection of code and context so as to allow a reader to diagnose the issue without needing to read all of your code or to engage in extensive back-and-forth dialog. For more information, see this meta thread." – Kromster says support Monica, bummzack, Anko, Seth Battin, congusbongus
If this question can be reworded to fit the rules in the help center, please edit the question.

  • \$\begingroup\$ The al stuff is the audio library, are you doing any audio stuff in your game? Perhaps not closing all streams? \$\endgroup\$ – bornander Mar 16 '15 at 12:48
  • \$\begingroup\$ No, no audio. The classes above are really the only classes in the whole game, besides the main game class which creates two screens and the runs setScreen(mainMenuScreen). \$\endgroup\$ – tsorn Mar 16 '15 at 14:15
  • \$\begingroup\$ Please narrow down your problem. Does this happen with an extremely simple game with almost nothing in it? \$\endgroup\$ – Anko Mar 17 '15 at 22:44
  • \$\begingroup\$ @Anko Yes, but the solution is posted below. \$\endgroup\$ – tsorn Mar 19 '15 at 12:13
1
\$\begingroup\$

Found the problem: Stage and Spritebatch needs to be initialized in the show-method (in both of the above methods).

From this:

public class MainMenuScreen implements Screen{
    SpriteBatch batch = new SpriteBatch();
    Stage stage = new Stage();

    public void show() {
        Gdx.input.setInputProcessor(stage);
    }

to this:

    public class MainMenuScreen implements Screen{
        SpriteBatch batch;
        Stage stage;

        public void show() {
            batch = new SpriteBatch();
            stage  = new Stage();
            Gdx.input.setInputProcessor(stage);
        }
\$\endgroup\$

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