Howto do input with gamestates

Sep 24, 2011 at 3:26 PM

Hi,

I'm a little lost with how to manage input within the gamestate framework.  Also, I am unsure that I am using the gamestates properly; so plese chime in if what I am doing is incorrect.  This is what I am doing:

- in my Game1.cs I create a GameStateManager and a few subclasses off GameState (StartGameState, LevelGameState, EndGameState).  In Initialise() I create an InputManager and setup a delegate to listen for keyPressed events.  In LoadContent() I instantiate StartGameState and push it on the GameStateManager.  note: I call update for the InputManager and GameStateManager in Update(); and call draw for the GameStateManager in Draw().

- StartGameState implements IDrawable.  Does it matter if I set the DrawOrder to always return 0; and Visible to always return true?  I don't know how to implement IDrawable properly and I have not yet found a tutorial which explains it in a way I can fully understand; especially within the context of Nuclex's GameStateManager.

- in StartGameState I store a reference to the InputManager.  I use this to setup a delegate to listen for keyPressed events.

What happens is I get both the Game1.cs and StartGameState delegates being called when a key is pressed.  What I want is for input handling to go with the GameState; just like the updating and drawing does.

I think I need to stop using events and handle input by hand in the Update menthod instead.  Is this the way everyone else is doing it?

Oct 3, 2011 at 7:11 AM

To stop input from propagating across game state changes I implemented an InputManager in my code.  It works in-between the Nuclex Input framework and the rest of my code; allowing me to 'mark' input events as having been processed so that when a game state changes I don't re-process the same input.

One thing I found is that the gamepad dpad doesn't cause any buttonPressed or buttonReleased events to be generated.  This is a bit weird because the Microsoft.Xna.Framework.Input.Buttons enum implies it will.  So I wrote some handling code in my InputManager to poll for the state of the dpad buttons every update.  This is exactly the code I was hoping to avoid by using Nuclex's Input framework :-(.  I also mapped the dpad values to LEFT, RIGHT, UP and DOWN; ignoring UP+LEFT, UP+RIGHT, DOWN+LEFT and DOWN+RIGHT.

It would be nice to have this as at least an option in the framework.  I'm happy to do the code if needed; I think all the changes would be contained to XnaGamePad.cs  If anyone else would find this functionality useful please say so and I'll see what I can do.  Assuming that code contributions are welcomed...

Oct 15, 2011 at 5:14 PM

Here's how my code works:

  • Each GameState takes in all the objects it requires through its constructor. For example, the "playing" GameState takes in a Player object.
  • The GameState is responsible for activating/deactivating the objects it takes in as it is opened, paused, resumed, closed etc.
  • The Player object only takes input from the InputManager when it is active.
Oct 15, 2011 at 9:48 PM

Thanks nlarooy.  That seems like a good way to manage it.  I think my problem would still exist even if I handled the input in the way you have described though.  However it has sparked some more thinking for me and now I see an alternative; and it is one of those painfully obvious ones which I wonder how I didn't realise it before.

The core problem is when a button is pressed and a game state changes the button press should not propogate across the game states.  e.g. press and hold A in gamestate1, switch to gamestate2; gamestate2 should ignore the A button press.  Why ignore A; because it has an associated action in gamestate2 which the player isn't really trying to perform e.g. in gamestate1 A quits the menu's, in gamestate2 A jumps the avatar.  The obvious solution is not to associate an action to A in gamestate2.  Doing this means that I wouldn't be able to re-use buttons across gamestates - no big deal really.

I think I'll do the activate/deactivate on each of my objects though.  That's a geat idea.  Thanks.

Oct 24, 2011 at 5:52 PM

My objects hook/unhook themselves from events when they are activated/deactivated.

So if an object is part of an inactive GameState (and so should be deactivated [although as you can see how my architecture would accommodate things if you didn't want it deactivated] ), then it will not handle any events sent from the InputManager.