   [C++, Design]Handling input, as in, state management.
  Hi. :)After finishing my generic, bind-able input manager, I want to use it to actually control stuff (obviously,hehe).I'm not sure how to make game objects use that input though, and I wonder if my method is redundant.Input is handled like this.Commands are registered.Keys can be bound to commands.Objects can subscribe to commands.Objects subscribe to commands by providing a receptor-function, and a value they want to be associated with the command.Like:input_manager.SubscribeToCommand(L"FK_FORWARD",entity.FORWARD,entity.register_input());then, when there is an input event, it goes like this:- input interpreter handles WM_INPUT (via 'ifs' since the amount of possibilities is manageable)- then it puts the data gathered into a container.- then the container is passed by reference to the manager- then the manager iterates through the list of all bound keys, and if there is a match, it calls the bound receptor function (a fast delegate) and passes the value the object bound to the command, as the argument.(which in essence could be considered being a specific event sent, right?)So, now we have reached the function inside the object.How do I elegantly manage states, and should I care about validity of input at that point?Or should I let the update function handle that?After all, in some cases, some input can be known to be invalid, even without updating.(For example if the object requires legs to jump, and it has lost them previously)Maybe a hybrid approach, pruning some obvious illegal ops there, and let the update function handle the rest?And how do I make all of these possibilities manageable?AiGameDev makes FSM appear outdated and not too flexible (albeit easy to implement) and favors Behavior Trees, but maybe that's overkill for this.I need state checking."If on ground and jump command is on the stack -> jump""If in air and jump command is on the stack -> jump again/do nothing"etc.I am thinking about having an array of handler functions bound as delegates, and an executor delegate which will be the one which gets invoked.The default value of that executor will be a root state, and the variables used in it will reflect the way the object was initialized (maybe it was spawned underwater, or in a vacuum, or in a fire, etc)Then when the input event arrives, the root function processes it, and if it successfully found a state transition, it modifies the executor value to point to the new state, which, upon the next update, process the input stack again, and does the same thing as the root did.This 'feels' nice to me, and I've read that state (bitfield/boolean,etc) checking, which seems as if it will pop up everywhere, is expected to be duplicated and found all over the place, appeasing the over-optimizer devil on my shoulder.So, should I go with this feeling? Or is there a tried and true solution to do these kind of checks?Well, any input is appreciated (no pun intended :P)Cheers :)   
  The translation from physical input to logical command seems ok. But I wouldn't try and incorporate an object's state into that too. An object should be able to receive a 'jump' command no matter what state it's in - let the object sort out what to do with it. At that point the command can be considered an intention and the rest is more of an AI question than anything else.   ;  Hmhm...thanks...Well, that's true, they should be intentions...I'm still not sure about how to implement the logic behind it though.I mean I know ways, but if-elses and the like aren't very maintainable...But yeah, should I have posted this in the AI forum?If yes, can it be moved there?Well, cheers :)   ;  It's impossible to tell you what to do to store and handle your current states without knowing what sort of game you have. There's no "one-size-fits-all" approach that will work for every game. You wouldn't implement a behaviour tree for Pong or Space Invaders but a variety of if-checks would quickly get out of hand in a complex scriptable RPG.It's also interesting that you're mixing input with AI. Normally you don't need things like behaviour trees for player characters - they don't need to make decisions about what to do next, as the player does that. It's as if you have your system working backwards. If there are certain actions that a player can't perform when in a certain state, that just needs to be wrapped up into properties of the player character which can be queried at the point where you process the intended commands, which may then change the player's current state. Behaviour trees are solving a different problem.   ;  What I did is give game entities an abstract IController object, to which they pass themselves as an IControllable. With a little extra infrastructure, this allows the behavior of entities to be almost completely separated from anything else, inside the controller. An entity could just as easily be controlled by user input as AI, if an appropriate controller was written and given to the entity.In my system, the only place where user input and the game entities intersect is in the InputController, which translates key-presses directly into actions of the entity it's controlling. It would be pretty easy to implement a more sophisticated system, though.   ;  Thanks for the replies :)@Kylotan:Oh, I didn't/don't want to mix AI per-se. I just thought I might be able to use some sort of pattern to deal with all those conditionals.I suck at explaining what I think, so I'll just give an example.An entity, regardless of the genre it lives in, usually has some sort of limitations what it can do, usually there will be conditions to deal with.As in, as much as I give the impulse to walk forward, if the object is running into a wall that is supposed to block it, it won't be able to do so.And as much as I press the swim upwards button, when there is no water, it cannot do it.I might also tell it to activate something even if there is nothing to activate nearby.Etc.Or how about a fighting game.You start with a clean slate, or a root state or however you want to call it.Then you press light punch, now you have a branch, one combo could be light punch x2, another light punch -> light kick, while any other key jumps into another branch.I could implement that in a single function littering it with ifs...but that really is a pain to maintain.So I figured that in the AI realm, such problems must be everyday fare, and thus there might be a tried approach to solving that kind of thing.After all, the fighting game logic could be represented as a FSM, right?-> light punch -> down -> fierce kick  root->light punch <-> light kick -> light kick -> fierce punch   \-> light punch etc.And lets say I want to extend or add a combo. should it be if/elses again?I'm not making a fighting game, but if/elses is what I use for checks if an action can actually be done, giving my test entity a truckload of booleans and a single function where everything is checked, resulting in a few needless CPU time, since some states entirely forbid certain inputs.I'm sure there must be a pattern, like a FSM or BT that handles such problems, and I'm interesting in finding it.Something that deals with conditions and branches, hence having looked at those two things first.@theOcelot:Hm, yeah I want something enclosed like that.And I can swap entities easily, everything deals with its input how it should.I just don't want to be stuck with single functions littered with if/elses, or too much code duplication in general.Edit:http://cowboyprogramming.com/2007/01/02/pushhing-buttons/I found an example...The CGuy object has no AI itself, but it uses logic, obviously, as well as states.The logic is split up into categories, like ground, jetpack, and air.This doesn't reduce else/ifs greatly, but it makes things more manageable, and I'd like to know if there is a sort of pattern or approach that is best suited for this kind of thing.   ;  I've always used some form of FSM. The best one I did was where every state had an init function, update function, and exit function. When the entity was updated, I just a single switch on an enum that described the current state, and called the appropriate update function. At any point, the update code could call the init function for another state, and that would change the state. Once all the overhead was taken care of, the logic looked pretty clean. I thought about using a class for each state, but that would have been even more code overhead.So if you took this sort of approach, within the update function for the state light_punch, you would check for the inputs that might lead to a light_kick or whatever, and then transfer to that state. The rules would be encoded in which inputs were checked for in the function.To make that sort of thing scale, you'd want a scripting system. That's my current project. That would also make it easier to do more complicated hierarchical states: you're doing a light kick while riding a jet-pack, what now?   ;Quote:Original post by EriusAn entity, regardless of the genre it lives in, usually has some sort of limitations what it can do, usually there will be conditions to deal with.As in, as much as I give the impulse to walk forward, if the object is running into a wall that is supposed to block it, it won't be able to do so.And as much as I press the swim upwards button, when there is no water, it cannot do it.I might also tell it to activate something even if there is nothing to activate nearby.Etc.These are examples of external state; properties of the environment that the will have to be checked before the entity can proceed. They don't typically stop the entity attempting the action, they just prevent its success. Sometimes you will still want to perform an action even though it won't work - eg. run on the spot when impeded by an obstacle, to show the player that their run key isn't broken.Quote:Or how about a fighting game.You start with a clean slate, or a root state or however you want to call it.Then you press light punch, now you have a branch, one combo could be light punch x2, another light punch -> light kick, while any other key jumps into another branch.These are examples of internal state; properties of the entity itself. Often these prevent an action entirely.Quote:So I figured that in the AI realm, such problems must be everyday fare, and thus there might be a tried approach to solving that kind of thing.After all, the fighting game logic could be represented as a FSM, right?-> light punch -> down -> fierce kick  root->light punch <-> light kick -> light kick -> fierce punch   \-> light punch etc.And lets say I want to extend or add a combo. should it be if/elses again?No, it's a trivial continuation of the FSM. Why should it be if/elses?Quote:I'm sure there must be a pattern, like a FSM or BT that handles such problems, and I'm interesting in finding it.This is a problem for FSMs. Behaviour trees are for AI characters to choose an action to take.Quote:Edit:http://cowboyprogramming.com/2007/01/02/pushhing-buttons/I found an example...The CGuy object has no AI itself, but it uses logic, obviously, as well as states.The logic is split up into categories, like ground, jetpack, and air.This doesn't reduce else/ifs greatly, but it makes things more manageable, and I'd like to know if there is a sort of pattern or approach that is best suited for this kind of thing.You could use an explicit State object, each of which handle your commands differently.class StandingState : public PlayerState{    virtual void handleJumpCommand() { player.transitionTo(new JumpingState); }    virtual void handleKickCommand() { player.transitionTo(new KickingState); }}class JumpingState : public PlayerState{    virtual void handleJumpCommand() { /* do nothing */ }    virtual void handleKickCommand() { player.transitionTo(new JumpingKickState); }}...etc...But really I think you're overthinking it. A few conditionals are not a high price to pay.;  Thank you very much for that detailed reply. I appreciate it muchly. :)Yes, I think you're right, I might be overthinking this, and you certailny pointed in a nice direction regarding separation / categorization of what affects what.Didn't think that through, internal vs external. Thanks. :)Well, gonna work on a simple state changer/manager then.Cheers!