JakaK
JakaK

Reputation: 1

LibGdx Screen: render and lifecycle

I have a problem, I think its related to Screen render and its lifecycle. Basically I have two screens (Menu and Game). In GameScreen render method i call World.update and after that my Render. In hide method (of GameScreen) i dispose of the SpriteBatch from Redner class.

So when I change the screen from Game to Menu (within World.update) Java crashes. As far as I can tell, the dispose is making the crash. So my question is, when i set a new screen in the middle of the render cycle, is that render cycle still going to finish with its old screen? Meaning, am I calling batch.dispose before the rendering was finished, and that is why i get the problem?

Thank you for all the help

public class GameScreen extends AbstractGameScreen {
    private static final String TAG = GameScreen.class.getName();

    private WorldController worldController;
    private WorldRenderer worldRenderer;

    private boolean paused;

    public GameScreen(Game game) {
        super(game);
    }

    @Override
    public void render(float deltaTime) {
        // Do not update game world when paused
        if (!paused) {
            // Update game world by the time that has passed since last render time
            worldController.update(deltaTime);
        }
        // Sets the clear screen color to: Cornflower Blue
        Gdx.gl.glClearColor(0x64 / 255.0f, 0x95 / 255.0f, 0xed / 255.0f, 0xff / 255.0f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        // Render game world to screen
        worldRenderer.render();
    }

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

    @Override
    public void show() { // Similar as create method
        worldController = new WorldController(game);
        worldRenderer = new WorldRenderer(worldController);
        Gdx.input.setCatchBackKey(true);
    }

    @Override
    public void hide() { // Similar to dispose method
        worldRenderer.dispose();
        Gdx.input.setCatchBackKey(false);
    }

    @Override
    public void pause() {
        paused = true;
    }

    @Override
    public void resume() {
        super.resume();
        // Only called on Android
        paused = false;
    }
}

Upvotes: 0

Views: 1751

Answers (1)

Tenfour04
Tenfour04

Reputation: 93581

That's basically correct. The screen that calls setScreen from within its render method will have hide called on itself and then will continue through the rest of its code in its render method. So you are killing your sprite batch right before trying to draw with it.

So don't call dispose from within your hide method. In fact, it is probably bad practice for a Screen to ever call dispose on itself. You can reserve that for the Game class that owns it. For example, you could do something like this in your game class:

@Override
public void render() {
    super.render();
    if (getScreen() != gameScreen && gameScreen != null) {
        gameScreen.dispose();
        gameScreen = null;
    }
}

By the way, you should probably put the SpriteBatch in your Game subclass and let all the different screens share it. It's a fairly big object to be allocating and deallocating for no reason.

Upvotes: 1

Related Questions