GameStates and GameControlManager

Hey all



I have an odd one here regarding GameStates and the GameControlManager.



In my test app, I have two GameStates - a menu and the ingame game state. To switch between the two, I use the Escape key. The initInput method for my menu game state looks like this …


controlManager = new GameControlManager();
GameControl esc = controlManager.addControl("esc");
esc.addBinding(new KeyboardBinding(KeyInput.KEY_ESCAPE));
ActionController gamemenuesc = new ActionController(esc, new GameControlAction() {
   public void pressed(GameControl control, float time) {
      System.out.println("pressed");
      gameGameState.setActive(true);
      gameMenuGameState.setActive(false);
   }
   public void released(GameControl control, float time) {
      System.out.println("released");
   }
});
this.getRootNode().addController(gamemenuesc);



... and the initInput method for my ingame game state looks like this ...

input = new FirstPersonHandler(cam, 10, 1);

controlManager = new GameControlManager();
GameControl esc = controlManager.addControl("esc");
esc.addBinding(new KeyboardBinding(KeyInput.KEY_ESCAPE));
ActionController ingameesc = new ActionController(esc, new GameControlAction() {
   public void pressed(GameControl control, float time) {
      System.out.println("pressed");
      gameMenuGameState.setActive(true);
      gameGameState.setActive(false);
   }
   public void released(GameControl control, float time) {
      System.out.println("released");
   }
});
this.getRootNode().addController(ingameesc);



I start out in my ingame game state. When I first press the Escape key, nothing happens. I see the "pressed" and "released" system outs, but no change in active game states. Then if I press Escape again, it works and I find myself in the menu game state. Then, if I press Escape from my menu game state, I get back into my ingame game state, but the screen does not refresh until I move the mouse (or issue some other FirstPersonHandler control).

The really strange thing is that once I have been through these two issues, the Escape key works as intended, swapping me between game states without any issue at all.

Any idea why my first run through these game controls might be showing these issues, and then working after that ?

Thanks all


Mak


Edit: Definately something to do with the Escape key triggering events on both game states the first time through. I can see that the "pressed" logic is running for the ingame game state and then immediately after (for the same key press) the "pressed" logic for the menu game state is running. That is why we are dropping back into the game game state. However, this doesn't explain why it only happens the first time through (I expect there's some sort of race conditions at play here) and also how a key pressed can be triggered after the key has been pressed in another game state.

Ok, frustration from the fact that I've been on this one problem now for 4 hours, has led me to make huge changes. I now only trigger the game menu from the Escape key in the game gamestate. So, the code is:


input = new FirstPersonHandler(cam, 10, 1);

controlManager = new GameControlManager();
GameControl esc = controlManager.addControl("esc");
esc.addBinding(new KeyboardBinding(KeyInput.KEY_ESCAPE));
ActionController gamemenu = new ActionController(esc, new GameControlAction() {
    public void pressed(GameControl control, float time) {
   System.out.println("pressed(game)");
   System.out.println("setting menugamestate "+!FD.menuGameState.isActive());
   menuGameState.setActive(!FD.menuGameState.isActive());
        gameGameState.setActive(true);
    }
    public void released(GameControl control, float time) {
   System.out.println("released(game)");
    }
});
this.getRootNode().addController(gamemenu);



This works just fine as a way of loading the menu over the top of the active game gamestate. However, as you see ...

gameGameState.setActive(true);

... I have to explicitly set the game gamestate active every time, even though I never set it to be inactive, otherwise it disappears when I activate the menu gamestate.

Any thoughts ? I have to say, my experience of GameStates so far has been a torrid affair.


Mak


ps. I'm doing all this in an extended BaseGame, and not using StandardGame. I understood that GameStates were not StandardGame dependant, but thought I'd mention this.

The first thing I would do if I were you is to remove any "actions" and simply do the system outs upon "press".  Verify that the actions are occurring exactly like they should.  If they are, then you know it has nothing to do with GameControls.  If it's not, then figure out what is happening unusual.



Try your best to narrow it down to explicitly what is causing the trouble (minimize what your application is doing) and that will probably show you what is wrong.  If not, at least its narrow enough that someone on the forums might be able to help you figure it out.



I actually do something quite similar to this in Galaxies Beyond to display the menu or to hide it, so I know it works when done properly. :wink:

I hear you df, but still no joy. Here's my test BaseGame:





Edit: Too much code !





Again, if I don't explicitly set the game gamestate active, it disappears when the menu gamestate has been activated. Never to return.



Any thoughts would be much appreciated.







Mak

I remember having a similar problem with GameStates which I just assumed was due to the way the input handling worked.



I thought the input handling worked by effectively checking the state of each key (pressed or not) on each update.  So you press the key which switches to the second state and then on the next update loop, which happens in a fraction of a second before you've managed to stop pressing the key, the key gets reported pressed again and your second game state switches back to the first.



I however didn't actually verify this and I wasn't using GameControls (which I assume just builds on the basic input handling anyway?)



So basically the above could be complete rubbish but maybe it'll give someone the "of course!" moment to actually help you solve the problem.

I've got everyone stumped with this one haven't I ? :slight_smile:



}:-@

Or perhaps you've posted more code than anyone wants to read through to help you. :wink:



I'm afraid you'll have to narrow the problem down further yourself. :slight_smile:

Fair enough :wink:

Thanks for that Hal. That is definately what I am seeing, but only on the first run through. After I have switched Gamestates once it's fine. Very perculiar. But, as froggie said, I need to drill down on this one myself and stop bothering you guys with reams of code.



I'll get back to this post if I ever get this solved, but was on it for 16 hours yesterday so I might just give up :wink:





Mak

Before I take a mallet to my computer, it would be great if someone could try this for me and see if they get the same effect. I have decided to take a working example from jmetest and see if I can change it to do what I want to achieve. So, I am working on the TestGameStateSystem example. This test shows a menu, you press Enter and it puts you into the game state. You press escape and it detaches the game state and activates the menu. You press Enter again and it creates a new game state, etc …



What I wanted to do was change it so that the game state was created and added to the GameStateManager at the start and was always active. The menu game state would then be activated/deactivated by the same Escape and Enter keys as in the original test.



So, to achieve this, I did the following:


  1. In the IngameState class, comment out the line that detaches the state:



    //GameStateManager.getInstance().detachChild("ingame");


  2. Add code to the initGame() of the main class to create the ingame state:



    protected final void initGame() {

      instance = this;

      display.setTitle("Test Game State System");



      // Creates the GameStateManager. Only needs to be called once.

      GameStateManager.create();

      // Adds a new GameState to the GameStateManager. In order for it to get

      // processed (rendered and updated) it needs to get activated.

      GameState menu = new MenuState("menu");

      menu.setActive(true);

      GameStateManager.getInstance().attachChild(menu);

      GameState ingame = new IngameState("ingame");

      ingame.setActive(true);

      GameStateManager.getInstance().attachChild(ingame);


    }


  3. Change the code in the MenuHandler to not create a new ingame state, but simply deactivate the menu:



    private class EnterAction extends InputAction {

        public void performAction( InputActionEvent evt ) {

    /*

    GameState ingame = new IngameState("ingame");

    ingame.setActive(true);

    GameStateManager.getInstance().attachChild(ingame);

    */


    myState.setActive(false); // Deactivate this (the menu) state.

        }

    }





    Now, if you run this, you'll see both gamestates active at the start. Hit Enter and sure enough you'll be in the game. Now, hit Escape for the menu and you will never see the Ingame State ever again even though it is never detached or deactivated !!



    If someone gets a chance to comfirm this for me, that would be great. I'm losing my mind here.





    Mak