• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Input Manager and FSM Question

A

atmobeat

Guest
I'm using an Input object that checks the hardware directly (among other things). My game is a zelda-like game with a focus on puzzles and has a mechanic or two that allow the player to control other characters, so I'm doing something a little different this time. After thinking about how to easily and clearly code such mechanics, I decided to have a variable called 'controlledInstance' initialized in my input manager object and then use a with-statement to perform user event 0 (reserved as a "Read Inputs" event in all objects my player can control).

I liked the idea for a few reasons: (i) it's not a huge deal but my input object checks the hardware in the begin step and the with-statement immediately has my controlled instance reacting to those inputs (kind of in-between the begin step and step events), so I can use the step and end step event for other things or even some more fine-grained ordering of things later if necessary; (ii) it's pretty clean as all the code for reading inputs is pretty decoupled from other things the object might be doing (especially nice for the enemies since their step event can focus on their normal AI state machine); and (iii) it's pretty straightforward for switching between objects (the code is only ever executed if that instance is actually the controlled instance, I don't need any checks for if my orc_warrior is controlled by the player character, and I don't need to introduce a truck-load of new states into their normal state machines). Maybe there are some other things I haven't thought about either.

After thinking about what is needed in my "Read Inputs" user event, it seems like I just need to put the entire state machine in there for those objects. This is because generally each state of the state machine reads the inputs in order to determine what state is next and then does other things associated with the state such as knowing when a state is being entered/exited, setting sprite indexes, playing sounds, etc. That seems natural, but my question (finally!) is this: is there some way to decouple the controls from the state machine and put them into my user event? Or better, is there some way to do that CLEANLY in a way that makes sense and isn't forced? Have any of you tried to do something like that? Is that kind of decoupling worth it?
 

Phil Strahl

Member
Hey atombeat! It's curious, I am exactly in the same process as you of decoupling things from each other as much as possible and am also toying around with prototyping a Zelda-like. The way I have things set up is the reverse of your implementation: Each entity (player, enemies, NPCs, etc.) have a controller variable. If they are controlled by the player, a reference to the global input manager is held there, if it's an enemy or NPC, it's an AI-controller object depending on their type.

I haven't sorted things out entirely, but it makes a lot of sense having the FSM be handles by the controller object(s). In the end, the entities themselves are just getting commands to move or act from their respective controller, not *when* to move or act.

In terms of abstraction, I would suggest decoupling things even further: Having an input controller that reads the hardware (in my game's case both keyboard and game pad), then having the appropriate FSM controller (depending on context, see next paragraph), and the entity (player, AI) that gets its commands from that FSM controller.

I've realized that "context" is important, so that when you're navigating a menu or something, you don't want your player entity to respond to the inputs, naturally.

I am not sure whether I answered your question, still I hope it helps you nevertheless :)
 
N

NeZvers

Guest
Maybe you need something like I explained here
I have separate controller object that reads player inputs in begin step and player object reads them in step event.
 
A

atmobeat

Guest
The way I have things set up is the reverse of your implementation: Each entity (player, enemies, NPCs, etc.) have a controller variable. If they are controlled by the player, a reference to the global input manager is held there, if it's an enemy or NPC, it's an AI-controller object depending on their type...

I've realized that "context" is important, so that when you're navigating a menu or something, you don't want your player entity to respond to the inputs, naturally.
That's certainly one way to do it but I don't like having a bunch of objects have that variable for a few reasons. For the 20 or 30 objects that have it, I might forget to put the variable in one of the objects' creation code (using parenting could help with this for many cases though). Second, when there's just one variable it prevents the situation you mention above of having several different objects being controlled at the same time. And as I mentioned above, you now have to have some kind of if check in every object to see what the variable is set to. I like this new strategy because now all I need to do is
Code:
with (controlledInstance)

     { event_perform(event_user(UserEvents.ReadInputs))  } ///ReadInputs = uv_user0
and that code is only ever executed when needed. No if-checks in every single object now and while running the user event, the enemy AI state machines are "turned off."

I haven't sorted things out entirely, but it makes a lot of sense having the FSM be handles by the controller object(s).
I may not have been clear, but I don't want my code for my FSM for my player character and enemies inside the controller object. I want that code in the appropriate objects, but inside a user event for that object. The controller object just tells which object to execute their Read Inputs user event. You probably didn't mean that, but I just want to be clear what's going on.

In the end, the entities themselves are just getting commands to move or act from their respective controller, not *when* to move or act.
I'm not entirely sure what you're getting at here but the first part is kind of what I was considering. The idea is that the user event will determine from the inputs what state the state machine will switch into, so the FSM itself doesn't check what inputs the player is pressing. The FSM itself (in the step event for the player at least) just makes sure the appropriate animations, sounds, timers, etc. are all doing the right thing. This is why it's "decoupling" the control-stuff from the normal state machine. I just don't know if that's worth trying and was wondering if anyone has done something similar.

I would suggest decoupling things even further: Having an input controller that reads the hardware (in my game's case both keyboard and game pad)
Check!

, then having the appropriate FSM controller (depending on context, see next paragraph), and the entity (player, AI) that gets its commands from that FSM controller.
That sounds close to what I said above. It might be that the user event is itself a FSM that reads inputs and outputs various states for a second FSM (what states to be in, transition to, and exit). The second FSM never reads inputs at all. It just receives states as inputs and outputs animations, sounds, times, etc. Though, it would probably have to interact with the other FSM. For example, suppose you want there to be a frozen state such that when the "normal" FSM is in a frozen state, the Read Inputs FSM can't output any states for the "normal" FSM.
 
A

atmobeat

Guest
Maybe you need something like I explained here
I have separate controller object that reads player inputs in begin step and player object reads them in step event.
My singleton controller object, and all my "system" objects (camera, menu, gui, etc), is created by a system spawner object in a loading room right at the beginning of the game. Also, I don't see anything about state machines in that post or decoupling inputs from the state machine.
 
Top