Sign in to follow this  
Sean_Seanston

Advice on separating Input from Entities

Recommended Posts

So I have a 2D shooter and the idea is that planes/vehicles/whatever should be separated from the means used to control them, i.e. player or AI. This would easily allow things such as switching between different vehicles and whatnot since the player's input handling etc. isn't embedded in the same object as a type of plane used by the player. I have more or less the idea drawn up. Entities will be controlled by EntityControllers, either of the Player or AI type. These controllers should somehow be able to command the same Entity object to do the appropriate things, regardless of being an AI or a player. The controllers will have a pointer to their controlled entity, or rather a list just in case more than 1 is ever needed. Ok in theory so far, right? How would be a good way to do that? I've had a few ideas flit through my head but I'm not sure if some are more work than required and less flexible than they should be, and I've been away from programming for so long that it'll take a while to start thinking right again. --- 1. Should I give all controllable entities a "library" of functions used to represent all of the actions they can take and then just have the controllers differ in a way such as: Player
if( W key down )
{
Entity->moveForward();
}
AI
if( Player ahead )
{
Entity->moveForward();
}
? This way you could probably even switch from very different vehicles with very different characteristics without much trouble if it was implemented right. I'm just worrying it may be somehow unwieldy in a way I haven't anticipated. 2. Some sort of messaging system where the player doing the action (pressing a key most likely) that should result in the entity doing something, causes some sort of message to be passed as an argument to an input handling function of the entity where appropriate action can be taken. This seems... perhaps less organized than the previous way and also seems like possibly just as much work for less neat looking code. Also, having moveLeft() and the like in their own standardized functions might have advantages. --- So that's what I have so far. Any problems with the first? I'm gravitating towards that right now.

Share this post


Link to post
Share on other sites
Hi,

Option number 1. will result in tons of functions. Every time you add a new type of button pressed you'll need to add a function too and that may result in lots of recompilations of code.


Option number 2. will result one function in the best case which will handle any type of input (keyboard, mouse, joystick ...).

I'd go for this way. Also, I'd implement sort of key binding system so that the entities don't handle the actual keys that were pressed but messages. So the entities would receive messages such as MOVE_FORWARD, STRAFE_LEFT, MOUSE_MOVEMENT, FIRE1, FIRE2 etc etc. With the binding system you can use any key for any action.

Cheers!

Share this post


Link to post
Share on other sites
i created classes for this, called them player, or actor, or what ever..

derived from this are aiplayers, and usercontrolled players. the players job is to a) think (if it's ai) or b) handle inputs and convert them to actual vehicle controls (if it's a player).

so what your vehicles expose are typical vehicle-controls (accelerate, break, turn left, turn right, shoot). and those players interact only trough those methods.


and then, i create for each wehicle a "Player Driver", which can be null, or some instance. and i go trough all vehicles, and if they have a driver in, get the drivers input feed to this vehicle.


something like this.

Share this post


Link to post
Share on other sites
Quote:
Original post by kauna
Also, I'd implement sort of key binding system so that the entities don't handle the actual keys that were pressed but messages. So the entities would receive messages such as MOVE_FORWARD, STRAFE_LEFT, MOUSE_MOVEMENT, FIRE1, FIRE2 etc etc. With the binding system you can use any key for any action.


Ya, I was thinking something using an enum. That would work fine, right?

Something like:

if( W key pressed )
{
Entity->input( MOVE_FORWARD );
}


for a player.

As for all the functions, I was thinking it would involve a lot of functions but then at the same time it would probably be less than 10 and most would apply to all vehicles. You'd mostly need to move in 4 directions and shoot. There probably wouldn't be even 10 so it might not be too unwieldy. Maybe though 1 input function would be more streamlined and just as good though.

Quote:
Original post by davepermen
so what your vehicles expose are typical vehicle-controls (accelerate, break, turn left, turn right, shoot). and those players interact only trough those methods.


So, more or less the same idea as 1 above? Have each vehicle present a set of move, shoot etc. functions that the player can interact with?

Share this post


Link to post
Share on other sites
I also vote for a mapping from "physical input" to "action input". The top solution would be that an InputControllable exposes what actions are provided in a common manner, so that an Input::Device (be it the keyboard, mouse, joystick, gamepad, wheel, ...) that is selected by the player is able to map its physical input possibilities to actions. The set-up can be changed by game state, so that also different vehicles may be controlled with different set-ups.

If interested in such a solution, you may have a look at e.g. unity's manual, Input section or Input Manager section, or even at USB HID specification if you're hard enough ;)

Share this post


Link to post
Share on other sites
#2 might result in only one function, but it will be a really ugly one, which has to change every time you change the capabilities of the entity. That won't be fun. It might be that the best you could make of it is to move all the actual actions into other methods, which puts you mostly back to #1. The only difference is that they can now be private (probably a good thing), and the translation of events to function calls takes place in the entity rather than the controller (might be bad).

If that didn't make any sense, ignore it. Anyway, the problems of abstracting input and abstracting control of entities are separate ones. If there is any direct translation from input events to entity actions, only the player-input controller will know about it.

Share this post


Link to post
Share on other sites
Quote:
Original post by theOcelot
#2 might result in only one function, but it will be a really ugly one, which has to change every time you change the capabilities of the entity. That won't be fun.


Yeah, that's what I was thinking. It's all mish-mashed together and nothing is in its own compartment like with #1 and both probably involve comparable amounts of work to implement.

Quote:
Original post by theOcelotThe only difference is that they can now be private (probably a good thing), and the translation of events to function calls takes place in the entity rather than the controller (might be bad).


Hmmm... yeah, probably makes more sense. Keep 1 big input function but have it manage the other ones that actually implement the behaviour. That probably is a good idea.

There aren't any glaring problems with my concept in general though? I think I'll go with #1 but with the single function controlling the private functions. Should be alright for my current purposes at least.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sean_Seanston
Hmmm... yeah, probably makes more sense. Keep 1 big input function but have it manage the other ones that actually implement the behaviour. That probably is a good idea.

That way, you can use a full-on object to pass commands, allowing you to pass an arbitrary amount of information to the entity. You might be able to inject a little extra flexibility by encoding part of the instructions in a string. Of course, if you find the strings getting too complicated, you probably want a scripting system.

This might not be as good as it sounds, though.
Quote:
There aren't any glaring problems with my concept in general though? I think I'll go with #1 but with the single function controlling the private functions. Should be alright for my current purposes at least.

Just that you may be making things far more complicated and messy than they need to be. Bear in mind the Single Responsibility Principle. Unless you can put almost all the command parsing in an Entity base class, which is unlikely, you are likely to wind up with a major violation of this principle, with event parsing code spread out between entity classes and scattered inside them, mixing with the actual game logic that's supposed to be in there.

You may be able to make it work, but you'll actually have to plan more carefully what kind of information passes through that one function to prevent it from turning into a hideous tangled mess. And you'll almost certainly need more than an enum if you want the system to scale farther than a very few kinds of entities.

You can make #1 work without constantly adding member functions to the entity interface. It may feel crazy at first, but if you put a little thought into the functions and make full use of their parameters, things will eventually settle down. I speak from experience with this approach.

You'll have to experiment with it. Perhaps you'll wind up with a hybrid approach, but whatever you do, don't let command interpretation get tangled with actual execution of the commands (game logic).

And again, don't forget that input handling is a different problem.

Edit: fixed link.

[Edited by - theOcelot on February 18, 2010 2:31:14 PM]

Share this post


Link to post
Share on other sites
I've always been partial to a setup like this:

1) Translation layer which converts raw/virtual codes (VK_H, VK_LBUTTON, VK_MOUSE_MOVE, etc.) combined with modifiers (up/down, ctrl/alt/shift) from the system into "game" codes. Some mappings are available to the user to be modified via configuration screens.

2) Handling layer which handles game commands on behalf of different systems or objects. Multiple handlers can be present (usually one for each system), in which case there's a simple process to determine who gets input, whether or not it's consumed, what order it gets processed in, etc. For some systems, like GUI, there's yet another translation/handling layer pair afterward that takes care of the GUI's specific needs. But for the most part, the handlers are the interface between game commands and whatever objects underneath that need input.

Share this post


Link to post
Share on other sites
Ok, I just discovered the huge problem with the way I decided to try to do this.

Basically, I sent enums like MOVE_UP, MOVE_LEFT, MOVE_RIGHT, MOVE_DOWN to the entity's input function depending on what key was pressed. Obviously, (though not to me when I was thinking of it) the entity needs to know whether or not it's moving in each direction and not just if it happens to now be moving in a new direction. Otherwise you end up going left then pressing up and releasing left but you're now going up and still left.

This naive implementation (no doubt partly due to being away so long) at least made me think about the matter more clearly. Somehow I'm going to need the Controller to send the complete state (as it relates to controls at least) the Entity should have to the Entity's input function. So whether or not it's moving left, whether or not it's moving up etc.

Obviously an enum system is no good whatsoever for this. However, some form of bitmask involving enums might be workable but definitely seems limited and more than a little clumsy to me.

So one way or another I'm going to have to have the Controller tell the Entity what overall state it should have. I can imagine some sort of EntityStatus class that's filled with all the info and sent off to the Entity but is that really a good idea? Also, if I wanted one variable of the Entity to change based on another variable I would then need to access those variables if I was merely filling an object with the new values the Entity should have and that seems to involve the Controller object in things it really shouldn't be doing.

Is there really any practical, beneficial way of doing this without a relatively complex messaging system of some kind? Maybe I should avoid it altogther.

In fact, here's my situation: I'm making a 2D scrolling shooter much like SWIV or Xevious as a college project and obviously that means limited time and no real necessity to do things in an ideal way. I'm intending to make a similar but expanded game after finishing this one, hopefully having learned some things.
Given the situation, do you think I should just hardcode the player as controlling 1 specific vehicle and have enemy AI hardcoded into theirs?
I'd like to do things as elegantly as possible but maybe it's just not worth it in this case and there probably wouldn't be any real benefit to this particular project if I got this Controller system working perfectly, it would be more of a good thing to know in the future.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sean_Seanston
Basically, I sent enums like MOVE_UP, MOVE_LEFT, MOVE_RIGHT, MOVE_DOWN to the entity's input function depending on what key was pressed. Obviously, (though not to me when I was thinking of it) the entity needs to know whether or not it's moving in each direction and not just if it happens to now be moving in a new direction. Otherwise you end up going left then pressing up and releasing left but you're now going up and still left.

Have complimentary events such as MOVE_UP_START, MOVE_UP_END, MOVE_RIGHT_START, MOVE_RIGHT_END, etc., and send the start event when a key is pressed, and the end event when a key is released.

Share this post


Link to post
Share on other sites

struct Input
{
Vec2 Movement; //[-1,1] representing joypad stick
bool Jump;
bool Fire;
};

class Character
{
public:
void SetInput(const Input& i)
{ mInput = i; }

void Update(float dt)
{
//utilize mInput
}

private:
Input mInput;
};


It's pretty easy to have ai control the entities when they're setup like this.

Share this post


Link to post
Share on other sites
Quote:
Original post by Zipster
Have complimentary events such as MOVE_UP_START, MOVE_UP_END, MOVE_RIGHT_START, MOVE_RIGHT_END, etc., and send the start event when a key is pressed, and the end event when a key is released.


So I tried that, using a keyboard event handler system I had built before instead of checking the state of the keys which I was using before.

I used
MOVE_LEFT_START
MOVE_LEFT_END

etc. and after some messing around it seems to now work fine for a player. I can't imagine any problems with an AI either so that seems good.

One question about the implementation though:
The way the keyboard system works, it has a map of function pointers associated with keys. To make a key perform a function, you put an entry in the table associating keys, a function and whether it's the key going up or down that it should be associated with. In the Window Procedure, it triggers the appropriate entry in the function table depending on what key has been pressed/released.

So, that means I can't exactly do things the way they were done before. Before I had the PlayerEntityController with an input function that checked the status of the keys and took appropriate action every frame, now because of the way the system works I've put the setting of the keyboard input handlers into the initialization function rather than input since there's obviously no need to put in a new entry of the same thing every frame.

Does this sound alright? It makes the controls seem a little distant from the PlayerEntityController class to me. I'm probably worrying about it for no reason though, since it still does control the setting of its associated keys. So what it does is, it sets the W key or whatever to call the input function of its controlled entities with some specific argument, e.g. MOVE_LEFT_BEGIN.

Another important thing though is that after doing this, if I held down 2 keys and moved diagonally then let go, the plane would often keep moving for a little bit before stopping like it should. So I figured there was some delay in processing the key events. I was confused for a while but today I noticed something. My messages in WinMain were handled by this:

//Handle messages
if( PeekMessage ( &msg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage ( &msg ) ;
DispatchMessage ( &msg );
}





So I was curious and changed it to this:

//Handle messages
while( PeekMessage ( &msg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage ( &msg ) ;
DispatchMessage ( &msg );
}





Now it appears to work perfectly. Should it have always been while? That seems to make more sense to me, the old system looked like it was just handling a single event every frame no matter how many were on the queue. Now it keeps going til none are left which sounds like it should account for the input lag before.
Just want to make sure that I'm not potentially breaking something that I don't fully understand.

Quote:
Original post by bzroom

struct Input
{
Vec2 Movement; //[-1,1] representing joypad stick
bool Jump;
bool Fire;
};

class Character
{
public:
void SetInput(const Input& i)
{ mInput = i; }

void Update(float dt)
{
//utilize mInput
}

private:
Input mInput;
};


It's pretty easy to have ai control the entities when they're setup like this.


Yeah... that's much like passing a structure of the state like I was thinking earlier. I suppose it's a bit like the system of enums only instead of FIRE_BEGIN and FIRE_END you have bool fire or some such. Might be more elegant if the amount of commands gets high. I'll have to see about that.

So I take it that Update takes action based on the contents of mInput, correct? Does that mean that SetInput() is called every frame to fill mInput with a new updated set of variables?

[Edited by - Sean_Seanston on February 21, 2010 2:13:10 PM]

Share this post


Link to post
Share on other sites
When you trigger the events, it still makes sense to send a little structure along with them that contains information about what triggered the event, if only for debugging and those odd cases where you will need it.

It's a trade-off between the number of unique events and the amount of logic performed outside the input system. For instance, you could have MOVE_LEFT_BEGIN/MOVE_LEFT_END events mapped to 'A' down/up, or you could just have a MOVE_LEFT event mapped to 'A' and send an up/down bit with the event so that game logic can check it. Or you just send raw key information and let the game do everything. It's a balance between shared logic in the input system versus game-specific logic in the entities and controllers. Our engine at work just has MOVE_LEFT/MOVE_RIGHT/etc. events that it sends along with information about the key/button that triggered the event, but this is mainly because our GUI layer requires untranslated events for edit boxes and the like and we don't want to create GAME_H_DOWN/GAME_H_UP events for every single keyboard key. In your case, individual events for everything might work just fine, it's really up to you.

Share this post


Link to post
Share on other sites
Quote:
Original post by Zipster
When you trigger the events, it still makes sense to send a little structure along with them that contains information about what triggered the event, if only for debugging and those odd cases where you will need it.


Alright so... the one global map of keys to functions is ok but I should use it to pass a whole structure instead of just a simple enum? With a pointer to the calling object maybe?

In that case should I just include the enum within a structure and add a pointer to the calling object etc.?

Share this post


Link to post
Share on other sites
Quote:

In that case should I just include the enum within a structure and add a pointer to the calling object etc.?



struct InputEvent
{
int Key;
int Event;
bool Pressed; //1 - pressed, 0 - released
float Value;
};




This is the kind of structure I am using at the moment for passing input to entities. So I have a translator class which converts the key to the actual event (the enum). I keep the key inside the class too for the rare cases it is needed.

the Pressed variable tells whether the key is pressed or released. So that I don't need separate event for releasing the key. Of course, that's up to you whether you want to have MOVE_FORWARD/MOVE_FORWARD_RELEASED events or just MOVE_FORWARD.

The float "Value" is used for input events such as mouse movement or analog joysticks.

I don't see a reason to pass the caller object. Perhaps you could explain why you'd want to do that.

You'll need experiment by yourself what kind of solution suits your needs.

Cheers!

Share this post


Link to post
Share on other sites
Quote:
This is the kind of structure I am using at the moment for passing input to entities. So I have a translator class which converts the key to the actual event (the enum). I keep the key inside the class too for the rare cases it is needed


Hmmm... yeah, that looks pretty good. Seems to make sense. Thanks.

Quote:
I don't see a reason to pass the caller object. Perhaps you could explain why you'd want to do that.


It was because of something Zipster said but now that I read it again I'm not sure if I misunderstood when he said:

Quote:
Original post by Zipster
When you trigger the events, it still makes sense to send a little structure along with them that contains information about what triggered the event, if only for debugging and those odd cases where you will need it.


I took "what triggered the event" to mean the object that triggered the event, but now I'm not sure if he meant the situation that triggered the event... surely the only thing you'd know for sure would be what key was pressed? Unless he was referring to the situation that caused the AI to trigger that event...

Share this post


Link to post
Share on other sites
OP:
You could also make a callback class, make player entity inherit from it and make it declare which actions do you need and where to send them.. and for the action mapping thing.. just declare an array of input elements which can be attached to a input reader which, then, changes some variables in that array so you could check for them in the player entity. That's how I do action mapping.

Share this post


Link to post
Share on other sites
What is the analogue inputs which used in the game.I like to know the leading concern which inventing and engaging in the field.I am interested in [url=http://www.thegamesupport.com]game support[/url].
your posts are highly giving the knowledge about the PC games.

Share this post


Link to post
Share on other sites
Quote:
Original post by stellamary
What is the analogue inputs which used in the game.


Just some thoughts:

You may consider mouse's movement or joystick's stick as analogue input. It means that the input event contains information about the scale/strenght of the movement. Moving a mouse generates an event which contains information how much the mouse has moved.

On the contrary, pressing a key on a keyboard generates event containing information which key is pressed down / released. It doesn't tell how strong you pushed the button (which would be nice some times actually).

Cheers!

Share this post


Link to post
Share on other sites
On Windows you can rely on WM_* messages for the keyboard and mouse, but for everything else you'll probably have to poll your input API. In that case you can wrap your own event system around the polling and send events whenever the values change (for both digital and analog inputs), or for analog inputs you can always rely on polling. Again it's up to you.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this