3

I started a project with libgdx and I have a GameStateManager for my GameStates Menu and Play.

If I run the project it shows the Menu and then I can click a button to open the Play GameState. The Problem is, that when I ended the Game it should show the Menu State again, but I get a black screen. I tested if the render() method is started (with System.out...) and the render() method in Menu is starting.

I am not shure why I get a black screen when I "reopen" the Menu state. Maybe its not working because I use Box2D in Play but I dont know.

Here some code:

This is the method in Play which should open the Menu if the player is at the end:

public void playerEnded() {

    gsm.setState(GameStateManager.MENU);

}

Maybe you can tell me, if I have to end box2d things or so. I hope someone can help me, and if you want more code - no problem.

3 Answers3

2

Your custom GameStateManager should extend this class:

http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/Game.html

To change screens you should be using Game.setScreen(Screen screen)

Each different screen should be an implementation of Screen.

So the way it works in my libGDX projects is such that GameScreen extends Screen, and MenuScreen extends Screen. That way I can change what draws on what screen.

This all goes back to interfaces and polymorphism, so if you don't get those concepts, just give it a quick google and you'll get an idea what you need to do.

Scuba Steve
  • 1,541
  • 1
  • 19
  • 47
1

Chances are that your are defining a

Stack<GameState> gameStates

in your GameStateManager to manage your GameStates.

If so, you could do some reading on using a Stack. Anyway, here's what could do to solve your problem: I'm assuming you have the following structure in your GamestateManager;

public void setState(int state){
    popState();
    pushState(state);
}
public void pushState(int state){
    gameStates.push(getState(state));
}
public void popState(){
    GameState g = gameStates.pop();
    g.dispose();
}

private GameState getState(int state){
    if(state == MENU) return new Menu(this);
    if(state == PLAY) return new Play(this);
    return null;
}

When you click your start button in your Menu-GameState, you'll want to launch the Play-GameState. Now, instead of using the setState method, which removes the top state (pop) and then pushes the new state. Try using only the pushState method. This will put your new Play-GameState on top of your Menu-GameState in the GameState-Stack.

When you're done playing, you can pop your Play-GameState and the Menu-GameState should reappear. But this time it won't instantiate a new Object, but reuse the one you used when you started the game.

// in the Menu-GameState:
public void startPlay() {
    gsm.pushState(GameStateManager.PLAY);
}

// in the Play-GameState:
public void playerEnded() {
    gsm.popState();
}

This won't affect gameplay performance as you would render and update your game with only the GameState that is on top of the Stack, like this:

public void update(float dt) {
    gameStates.peek().update(dt);
}

public void render() {
    gameStates.peek().render();
}

The peek method takes the GameState from the top of the Stack, but leaves it there.

The only downside is that the Menu-Gamestate would stay in-memory during your Play-State.

Also, if this method works, you could still do it your way, but you should check the way your Menu-GameState is instantiated and identify problems when it's instantiated twice.

RDO
  • 56
  • 6
0

I implemented a similar StageManager in my game. If you are using viewports/cameras in your game, then it is likely that when you go back to your menu state, the viewport is still set to the Game state's viewport.

For my app, I had my State class have an activate() method which would be called whenever a state became the active state:

public void activate(){
  stage.getViewport().update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}
spectacularbob
  • 3,080
  • 2
  • 20
  • 41