# How to architect input code to utilise state machine?

I have an InputController which currently handles all user input, so it looks at button states and updates entity intentions according to some simple rules.

I'm looking to add a new state to the game which essentially means displaying the player's inventory on screen. During this state I want the background to continue animating but want the user input to only interact with the inventory layer.

As the code stands right now the background will animate just fine under the inventory layer but the InputController will continue to behave like the layer isn't there and attempt to map clicks etc. to the game world.

An easy solution would be to add simple conditional logic in the controller if (currentState == x) but wondered if I could better utilise my existing game state machine. I have states such as game_loading, in_game, menu etc.

The only ideas I can come up with is either calling out to something like state.HandleInput() from inside the controller, that way the state is in control of what the player can and can't do but the downside is that input specific logic is being handled by a state rather than input specific code, which I'm not comfortable with.

Alternatively, I could reverse that and get the state to be the entry point and then they call out to specific input classes. So something like inGameState.HandleInput() calls out to inGameInputController likewise with inventoryState. This seems like the better approach.

I'm clearly not sure which way round the dependencies should orient. Am I missing a layer of abstraction somewhere? Or am I overcomplicating things?

You aren't over complicating it at all. This is a great way to think about a game. It keeps the game flexible for any changes you want to add in the future (say a stats screen).

The first place I would look is using the Strategy Pattern: Wikipedia

Determine what input triggers you would need and add them to an abstract interface. Then, implement the interface for each game state. Keep track of what your current state is and forward any of those input triggers to the current state to handle what ever it is you want to handle.

I 'll try to manage InputController changing its behaviour at runtime (in c# can use some kind of delegates) Examples :

if activated in_game state then InputController.processInput = logic1

if activated menu state then InputController.processInput = logic2

if activated inventory state then InputController.processInput = logic3


Logic1..N are alternative implementation of input processing

In instances like this I use a stack of input maps. You already have certain buttons doing this or that while playing the game, if you can group that logic into a map (array of button/key => some event) then you can make multiple maps for the different states you have. From there you just need 'some event's that can be used to push and pop the maps from a stack.

I generally make the 'menu' map the initial one and so it can not be popped off, it is the one always around. When you go into a game I would push on the 'playing the game' map and so the inputs would then cycle through there. One of the inputs to go back to the menu would have to, ofcourse, toggle your menu on, but then just pop off the 'playing the game' map.

Edit: An extended feature you could add into this would be for partial or fallthrough maps. This would allow you to change some of the buttons but still use the majority of the existing maps. A use case for this would be having items you can use bound to the directions on a D-Pad and having a second button (a bumper or the like) be held down or tapped to toggle it to a second set of items to use instead.

Any questions feel free to ask, I have tried to keep this simple but it may be I can find a better way to explain.

• I currently have the cursor represented using an Entity and I check for Entity->Entity collisions and then raise events. So cursor->item collisions would behave like a hover event where I then print the name of the item to the screen. This is specifically what I'm looking to alter depending on the state. Would you still solve this type of problem with the solution in your answer? – Adam Naylor Aug 4 '15 at 11:15