• Create Account

# Input handling design frustration

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

16 replies to this topic

### #1SonicD007  Members   -  Reputation: 453

Like
0Likes
Like

Posted 06 December 2013 - 11:19 AM

So I've been reading through this article and messing with it for close to a month (on and off because of work and school) and I understand it for the most part.  I changed the code a bit so I could use SDL_Keycodes for the SetRawButtonState methods and whatnot and got all that working.  My problem comes with the function pointer that InputMapper uses to do any actual work based on the input.  Most likely my brain is just overworked and I can't properly think this through...

So, how would I have my gameObject handle the input that is received?  I want the individual game object to act on the input that was received so how would I do this exactly?

Would I need to do something like this?  If so, how can I also pass the struct that inputMapper uses that holds the information on the actions and states?

P.S. I'm rusty with function pointers so that could be my issue.

### #2dejaime  Crossbones+   -  Reputation: 2505

Like
0Likes
Like

Posted 06 December 2013 - 01:51 PM

There are multiple approaches to this problem, I'll list some here, just to give you something to think over.

When I was doing my very first prototypes that actually used input, I usually did a hard-coded check with an input class. This class, when detected something, called a function directly on an object that was derived from my PlayerObject class. It was really amateur, rude, but worked fine since I only had to worry if a button was up or down...

Later on, I decided to use this callback system. So, I had a function that read the input keys from configuration data somewhere (like JumpKey: KB_KEY_SPACE). With those configurable key values loaded, I registered callback functions on my input class.

The one I use on most of my projects today is a simple event system. Whenever a change is made on input (Let's say KB_KEY_SPACE is pressed), an event is generated (class EvtJump: public EvtInput) and sent to every registered event listeners. It has an more flexible implementation than simple callbacks, but some would argue it is less optimized. I wouldn't worry this much about it since mostly you'll have only a handful of events to handle every frame.

This last one is specially preferable since it is easier to create different input types like press and hold. With callbacks I usually messed my entire code up to do simple evaluations in order to call the correct callback...

I'm not saying it is the best approach to every case, but it suits my needs on most cases. Specially because I also use events on things in the game physics simulation and overall logic.

If you want some help on this approach, just shout

### #3SonicD007  Members   -  Reputation: 453

Like
0Likes
Like

Posted 06 December 2013 - 02:24 PM

The one I use on most of my projects today is a simple event system. Whenever a change is made on input (Let's say KB_KEY_SPACE is pressed), an event is generated (class EvtJump: public EvtInput) and sent to every registered event listeners. It has an more flexible implementation than simple callbacks, but some would argue it is less optimized. I wouldn't worry this much about it since mostly you'll have only a handful of events to handle every frame.
This last one is specially preferable since it is easier to create different input types like press and hold. With callbacks I usually messed my entire code up to do simple evaluations in order to call the correct callback...

I've never programmed event systems before.  I've used C# events with winforms and understood the concept, but I never sat down and tried to create something similar using c++.

My goal at this point is to have a system where if I press up, my character will move up. If I hold up and right, my character will move diagonally.  Do you think you can post a sample piece of code using your event system just so I can see how you're handling the presses at the object level?

I'm interested in how other people have solved this issue.

### #4Vortez  Crossbones+   -  Reputation: 1509

Like
0Likes
Like

Posted 06 December 2013 - 03:09 PM

Im not very good at explaining, so let me show you how i did with my game engine

// .h

class CVortez3DEngine {

// some stuffs removed...

public:
virtual void OnChar(UINT Ch){}
virtual void OnKeyDown(UINT KeyPressed){}
virtual void OnKeyUp(UINT KeyReleased){}
public:
virtual void OnMouseDown(int ButtonPressed, int x, int y){}
virtual void OnMouseUp(int ButtonPressed, int x, int y){}
virtual void OnMouseMove(int x, int y);
virtual void OnMouseMove(int x, int y, int XDisp, int YDisp){}
virtual void OnMouseRoll(int RollCount){}
}

class CVortez3DEngineExt : public CVortez3DEngine {

// some stuffs removed...

public:
void OnChar(UINT Ch);
void OnKeyDown(UINT KeyPressed);
void OnKeyUp(UINT KeyReleased);
public:
void OnMouseDown(int ButtonPressed, int x, int y);
void OnMouseUp(int ButtonPressed, int x, int y);
void OnMouseMove(int x, int y);
void OnMouseMove(int x, int y, int XDisp, int YDisp);
void OnMouseRoll(int RollCount);
};

// .cpp

CVortez3DEngine *pVortez3DEngine = NULL;

// ...

//-----------------------------------------------------------------------------
// Process the windows messages
//-----------------------------------------------------------------------------
LRESULT CALLBACK MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
//Process quit message
case WM_DESTROY:
case WM_CLOSE:
PostQuitMessage(0);
break;

// some stuffs removed...

// Keyboard messages, for text...
case WM_CHAR:
pVortez3DEngine->OnChar((UINT)wParam);
break;

// Keyboard messages, , for keys...
case WM_KEYDOWN:
if(wParam == VK_ESCAPE && pVortez3DEngine->GetUseEscKeyToQuit()){
PostQuitMessage(0);
break;
}
pKeyState[wParam] = true;
pVortez3DEngine->OnKeyDown((UINT)wParam);
break;
case WM_KEYUP:
pKeyState[wParam] = false;
pVortez3DEngine->OnKeyUp((UINT)wParam);
break;

// Mouse move messages
case WM_MOUSEMOVE:
pVortez3DEngine->OnMouseMove(LOWORD(lParam), HIWORD(lParam));
break;

// Mouse buttons messages
case WM_LBUTTONDOWN:
pMouseBtnState[LEFT_MOUSE_BUTTON] = true;
pVortez3DEngine->OnMouseDown(LEFT_MOUSE_BUTTON, (int)LOWORD(lParam), (int)HIWORD(lParam));
break;
case WM_LBUTTONUP:
pMouseBtnState[LEFT_MOUSE_BUTTON] = false;
pVortez3DEngine->OnMouseUp(LEFT_MOUSE_BUTTON, (int)LOWORD(lParam), (int)HIWORD(lParam));
break;
case WM_MBUTTONDOWN:
pMouseBtnState[MIDDLE_MOUSE_BUTTON] = true;
pVortez3DEngine->OnMouseDown(MIDDLE_MOUSE_BUTTON, (int)LOWORD(lParam), (int)HIWORD(lParam));
break;
case WM_MBUTTONUP:
pMouseBtnState[MIDDLE_MOUSE_BUTTON] = false;
pVortez3DEngine->OnMouseUp(MIDDLE_MOUSE_BUTTON, (int)LOWORD(lParam), (int)HIWORD(lParam));
break;
case WM_RBUTTONDOWN:
pMouseBtnState[RIGHT_MOUSE_BUTTON] = true;
pVortez3DEngine->OnMouseDown(RIGHT_MOUSE_BUTTON, (int)LOWORD(lParam), (int)HIWORD(lParam));
break;
case WM_RBUTTONUP:
pMouseBtnState[RIGHT_MOUSE_BUTTON] = false;
pVortez3DEngine->OnMouseUp(RIGHT_MOUSE_BUTTON, (int)LOWORD(lParam), (int)HIWORD(lParam));
break;

//Mouse wheel message
case WM_MOUSEWHEEL:
{
int RollCount = (signed short)HIWORD(wParam) / WHEEL_DELTA;
pVortez3DEngine->OnMouseRoll(RollCount);
}
break;
// Process other messages
default:
OnCustomMessage(uMsg, wParam, lParam);
break;
}

//Return result to windows
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////

// int the file using CVortez3DEngineExt

//-----------------------------------------------------------------------------
// OnKeyDown event...
//-----------------------------------------------------------------------------
void CVortez3DEngineExt::OnKeyDown(UINT KeyPressed)
{

}

//-----------------------------------------------------------------------------
// OnMouseDown event...
//-----------------------------------------------------------------------------
void CVortez3DEngineExt::OnMouseDown(int ButtonPressed, int x, int y)
{

}

//-----------------------------------------------------------------------------
// OnMouseUp event...
//-----------------------------------------------------------------------------
void CVortez3DEngineExt::OnMouseUp(int ButtonPressed, int x, int y)
{

}

//-----------------------------------------------------------------------------
// OnMouseMove event...
//-----------------------------------------------------------------------------
void CVortez3DEngineExt::OnMouseMove(int x, int y, int XDisp, int YDisp)
{

}



All im doing is creating virtual functions, overriding them later with another class, and react to OnMouseMove(), OnKeyDown() ect...

If you don't declare them in the CVortez3DEngineExt class, it will use the default ones (empty functions) supplyed in CVortez3DEngine, so, you don't have to use all the events if you wish, they are optional, that's the great part about it.

Edited by Vortez, 06 December 2013 - 03:16 PM.

My 3D Engine.

### #5SonicD007  Members   -  Reputation: 453

Like
0Likes
Like

Posted 06 December 2013 - 08:36 PM

Did you have the objects that needed to handle input register themselves to that class as a listener object and have that class somehow notify the objects that need to react on the input when the event was triggered?

### #6Vortez  Crossbones+   -  Reputation: 1509

Like
0Likes
Like

Posted 06 December 2013 - 08:59 PM

Did you have the objects that needed to handle input register themselves to that class as a listener object and have that class somehow notify the objects that need to react on the input when the event was triggered?

I dont really understand what you mean by that. All im doing is to respond to windows inputs messages in the message pump of my application.

If i was to use the class "as it is" ie. CVortez3DEngine(), nothing would happen because

virtual void OnMouseDown(int ButtonPressed, int x, int y)

{

}

is an empty function.

The key here is the virtual keyword. When i extend the class CVortez3DEngine() using inheritance, i have the option to "override" those functions. Than mean if i do this

class CMyGame : public CVortez3DEngine {

public:

void OnMouseDown(int ButtonPressed, int x, int y);

}

now 2 things happen.

First, CMyGame can do everything that CVortez3DEngine can do.

Secondly, i created another function with the exact same name and arguments, but without using the virtual keyword.

That mean, when the call to OnMouseDown is made in the message pump, it dosen't call the empty function anymore, it will call the later one from CMyGame.

That might seem a bit confusing, but it's not that hard, maybe my example is a little bit overwhelming for your current programming skill, that's normal,

i was a beginer too a few years ago.

Edited by Vortez, 06 December 2013 - 09:01 PM.

My 3D Engine.

### #7SonicD007  Members   -  Reputation: 453

Like
0Likes
Like

Posted 06 December 2013 - 09:15 PM

I understand the virtual functions you're using.  What I'm trying to figure out is if you have something similar to this:

CVortez3DEngineExt::OnChar(UINT c)
{
Game::playerObject.HandleInput(c);
}


or if it's more like

CVortez3DEngineExt.TriggerEvent(OnChar('A'));

//player object gets a message notifying it of this event to handle input (event delegation? haven't programmed this before so not sure how it would look
playerObject.HandleInputEvent(CVortez3DEngineExt::SomeInputStruct);
//playerObject.HandleInputEvent would then look at the struct and do stuff based on that


I want to do something similar to the second code box I just wrote out.  I want the player class to do something based on input.  I don't want the input class to tell the player class what to do per say

### #8Vortez  Crossbones+   -  Reputation: 1509

Like
0Likes
Like

Posted 06 December 2013 - 09:25 PM

To be honest i don't have anything special to handle inputs like your talking about, i just use the value. I guess for mapping keys an input handler would come in handy, yea.

My 3D Engine.

### #9L. Spiro  Crossbones+   -  Reputation: 8815

Like
4Likes
Like

Posted 06 December 2013 - 09:52 PM

Inputs are not events.
I reiterate from that post, game objects do not handle their own inputs.  A callback system in which game objects assign handlers for certain inputs is not only a flawed approach in scope but convoluted and hard to debug/manage.

L. Spiro

Edited by L. Spiro, 06 December 2013 - 09:54 PM.

It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

### #10dejaime  Crossbones+   -  Reputation: 2505

Like
0Likes
Like

Posted 08 December 2013 - 07:01 AM

I've never programmed event systems before.  I've used C# events with winforms and understood the concept, but I never sat down and tried to create something similar using c++.

My goal at this point is to have a system where if I press up, my character will move up. If I hold up and right, my character will move diagonally.  Do you think you can post a sample piece of code using your event system just so I can see how you're handling the presses at the object level?

I'm interested in how other people have solved this issue.

Sure thing, I'll scavenge my old code and post here soon. It'll probably be delayed a little, I am removing Ubuntu from all my machines due to those Amazon features. It's taking me quite some time...

Edited by dejaime, 08 December 2013 - 07:12 AM.

### #11L. Spiro  Crossbones+   -  Reputation: 8815

Like
1Likes
Like

Posted 08 December 2013 - 08:27 AM

Sure thing, I'll scavenge my old code and post here soon. It'll probably be delayed a little, I am removing Ubuntu from all my machines due to those Amazon features. It's taking me quite some time...

You posted 2 ways you approached the problem.
Did you consider the 3rd option that was posted?

Because things such as physics happen on a routine basis. If I can’t jump while in the air I might either need to do a verify of an “isOnGround” flag or ask the physics engine if I am on the ground in order to know if I am able to jump again when the button is pressed.

Since the physics routine is called on each frame at a specific time within that frame, maybe it would be best to just use that call for all the information related to input?
I mean instead of a player spamming input into a keyboard and having the in-game character invoke a million physics queries, perhaps it would be better to just stick to the main game loop and buffer things such as, “isOnGround”, etc. Perhaps physics can be made more efficient by dividing it into a PrePhysics(), Physics(), and PostPhysics() set of calls. Yes? Something that would not be possible if characters handle their own input routines.

And I really hate repeating myself, but that is just the overall framework point-of-view. It ignores the obvious (which I already mentioned) problem in which a character knows what physics is. The character does not control the game. The game controls the character.

This last one is specially preferable since it is easier to create different input types like press and hold. With callbacks I usually messed my entire code up to do simple evaluations in order to call the correct callback...

Compared to simple callbacks, your system is a shift in the right direction, but not the best way for the example you provided in which you can hold keys etc.

If you play a modern fighting game such as Persona 4 Arena or BlazBlue: Chronophantasma in training mode, the keys you have pressed are shown on the bottom and span the entire screen length.
Why? Because they handle input the way I described. As a log.
And with inputs as a log you can easily detect the correct input codes for an attack (and I am using a fighting game here as an example because it is the best example of input complicated enough to be suitable for any other type of game).

With an input log, as described by my previous post, you can easily look back and see if a move should be converted to a combo-button hit-button release attack or a button-hit-combo-button release attack. And if neither of those, then if the last button hit was A, do a standard weak attack.

With input becoming exponentially more complex you need the same rate of branch-explosions in order to handle every order of every case.
Look at my example and think about parsing it.
“A was just hit. Look back. Last 3 inputs were 236 (for those not in the game, that’s D, FD, F (for those not in the game, that’s Down, Forward-Down, Forward (for those not in the game, that’s a Ryu fireball (for those not in the game, Ryu is a character from Street Fighter, and he has a fireball, which is done by pressing 236-Y)))), and 236A makes a valid attack. Look back. If B was pressed just before that, it is a super attack. Look back. If B was pressed, held for 2 seconds, and then released, the 236A attack becomes overpowered, but only if the player’s gauge is maxed.

See how this could start to suck trying to parse event-by-event in real-time?
Keeping a log and parsing it at a specific time during the frame is the only way to go.

L. Spiro
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

### #12SonicD007  Members   -  Reputation: 453

Like
0Likes
Like

Posted 08 December 2013 - 08:57 AM

Okay, so what I've gathered from this is that I'm going about this the wrong way in that my game objects shouldn't handle the input themselves, but rather the game class (whatever class that knows the rules of the game and resources) would handle the input and act upon my game objects accordingly, right?

My input class should have a stack of inputs mapped actions/States which are read during a specific point in the game loop each frame.  Maybe something like

//inside CGame
void CGame::Run()
{
//Inside while loop of running game
//Get inputs
input->GetInput(); //Maps raw input to state/action and stores into a structure which is pushed onto a stack.  End of stack gets erased (sidenote: is a stack what I want to use here?)

//This is what I want to do but isn't what should be done from what L. Spiro said
//Active context could be inventory, playing field (so input goes to the character), etc.
// this->ActiveContext.HandleInput(input->GetInputStack());

//This is the correct way?
switch (ActiveContext.ID)
{
case Context::GAME:
//Again, how should I handle the input here?  If I have two buttons pressed I would want a move diagonal, not a move up which then gets changed to a move right when the right arrow is pressed.  I think this is also one of my big issues.
break;
//Other contexts like inventory
}

//Do other logic/rendering (well rendering would go somewhere else in a fixed frame rate loop)
}

void ActiveContext::HandleInput(inputStruct* inStruct)
{
//Handle states
//I'm not sure how I should do this part. a bunch of if and else can't be good
if (inStruct.states.find("UP")
//And this is where my design would fail because now ActiveContext needs to know about gameObjects which it shouldn't...hmm...
}


Let me know if anything I wrote isn't clear or hard to understand.

EDIT: all my tabs got removed for some reason

Edited by SonicD007, 08 December 2013 - 08:58 AM.

### #13dejaime  Crossbones+   -  Reputation: 2505

Like
0Likes
Like

Posted 08 December 2013 - 07:10 PM

See how this could start to suck trying to parse event-by-event in real-time?

Keeping a log and parsing it at a specific time during the frame is the only way to go.

L. Spiro

I think I don't understand the problem you highlighted, so I'll explain better my event system and you can point me exactly where is the problem.

I never hardwire an input event to a reaction on the physics system or through any sort of direct connection. Even with an event based system, every event has to be remapped somewhere and turned into useful information. Otherwise, it generates a tight dependency on the platform. I deemed that mention unnecessary since the journal post by ApochPiQ goes all the way through input re-mapping and forward.

If you allow me an example, imagine a situation where the character can jump and then use a jetpack to keep on going up. In this case, character could jump and simply fall down by pressing jump. It could jump, activate the jetpack to keep on going up, and then releasing it to fall down to the ground again. A third possibility would be to jump, jet up, turn the jet off (by releasing the jump key) and then activating it again by pressing it before landing on the ground.

In this specific case, the jump key would generate a key down event that would be logged and remapped into an action somewhere else. From there, the input system wouldn't exercise any control over what happens, since its job was simply to detect and remap the input. So, if the character is on the ground it would need to jump, if he was on air it would turn on the jets.

We would then have some code that gets the action, the entity, and tries to apply that action to that entity somehow, be it a detachable physics component or something else.

Still, none of these actions would need to be applied as soon as they were received, they could even be sent to another thread or anything necessary.

So, in a time line, this is what happens:

• Button is pressed

• Event is generated with any wanted information

• the input type

• time of generation

• maybe the entity it refers to (depending highly on the game's implementation)

• misc info like button pressure, thumbstick position […]

• Event is queued for remapping sometime (and waits there for the game to start remapping input events)

• Events gets remapped

• The remapping verifies the event log to find any possible gesture match (say, ↑ ↑ ↓ ↓ ← → ← → B A), checks the time between repeated taps, anything necessary to interpret the input

• Event is interpreted creating an specific action

• Action to be applied to something is created and maybe queued or sent to another thread or even something else

• Event goes to a past event pile or list (flushed by some game specific logic or simply with a fixed size)

• Action is applied to the character externally to it

• In case of a physics action, the physics component of the entity or some external handler interprets the action and applies it, if valid

This is how I usually go for my input gathering. It may not be a performance marvel or anything, but it suits most of my projects.

Edited by dejaime, 08 December 2013 - 07:15 PM.

### #14L. Spiro  Crossbones+   -  Reputation: 8815

Like
3Likes
Like

Posted 09 December 2013 - 07:31 AM

//This is the correct way?
switch (ActiveContext.ID)
{
case Context::GAME:
//Again, how should I handle the input here?  If I have two buttons pressed I would want a move diagonal, not a move up which then gets changed to a move right when the right arrow is pressed.  I think this is also one of my big issues.
break;
//Other contexts like inventory
}

No. The article by ApochPiQ mentions context-sensitivity, but high-level context is implicit when you organize your game into modules like this.

Within a game state, subcontexts are better handled via a stack of contexts as mentioned by ApochPiQ rather than via a switch.

I never hardwire an input event to a reaction on the physics system or through any sort of direct connection.

That was meant for him

In this specific case, the jump key would generate a key down event that would be logged and remapped into an action somewhere else.
…none of these actions would need to be applied as soon as they were received, they could even be sent to another thread or anything necessary.

Re-mapping an input is simply a means of translating hardware-specific to something that the game can understand universally across platforms. For keyboard keys and gamepad buttons it simply means converting the platform-specific keycode or button code to an enumerated ID understood by the engine. This ID, along with its time-stamp and any other useful information about the input such as pressed/released state, are stored in a structure that you might call a mapping or translation.  This is what is queued.

Then there is a second mapping phase, in which keys are remapped.  This sends the mapped keys through the user options and allows the user to change the button/key assignments.  The same “mapping” structure is used to hold the new information but the key/button ID is changed, the Y axis is inverted, etc.  This happens when inputs are taken off the queue, not before, or else you can screw up the input-configuration menu of your game when the remappings of keys/buttons change in real-time.

These are often called the “translation” and “mapping” stages respectively, but to align with the article I will call them “mapping” and “remapping”.

I have explained in detail how to take things off the queue here.  The queue typically should exist on a second thread but the implementation is the same either way, so for starters you don’t have to multi-thread your input.  But it will be easier to think of who is responsible for what tasks, so I will assume a setup in which input is handled on thread A and the game loop is on thread B.
And remember, it is when the inputs are taken off the queue that they are remapped based on user input configurations and then logged.  The queue exists on thread A and thread B grabs from it as described by my above link.
Then the log is parsed for key combinations etc. on thread B.  Thread A has done its job now.
Then in-game actions can be generated.  In contrast with your implementation, generated in-game actions should not be generated by thread A and then sent to another thread etc., but rather what should be on the other thread and “held until needed” is the queue of mapped (not remapped) inputs on thread A.  Thread B should take from the queue, remap, log, and interpret into in-game actions all at once at a specific time in its execution cycle.

So, in a time line, this is what happens:

• Button is pressed
• Event is generated with any wanted information
• the input type (mouse, keyboard, button, etc.)
• time of generation
• maybe the entity it refers to (depending highly on the game's implementation) (The input module has no idea what an in-game entity is.  Use this space to insert button state such as pressed/released)
• misc info like button pressure, thumbstick position […]
• Event is mapped and then queued for remapping sometime (and waits there for the game to start remapping input events)
• Events gets remapped
• ​User input configurations are applied and the result is sent to the log
• The remapping verifies input interpreter checks the event log to find any possible gesture match (say, ↑ ↑ ↓ ↓ ← → ← → B A), checks the time between repeated taps, anything necessary to interpret the input
• Event Log is interpreted creating an specific action by a high-level class that knows the game rules and has access to all modules of the game, including the physics engine, etc.
• Action to be applied to something is created and maybe queued or sent to another thread or even something else then immediately executed
• Event goes to a past event pile or list (flushed by some game specific logic or simply with a fixed size)
• Action is applied to the character externally to it Action has already been applied
• In case of a physics action, the physics component of the entity or some external handler interprets the action and applies it, if valid

L. Spiro

Edited by L. Spiro, 09 December 2013 - 09:46 AM.

It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

### #15dejaime  Crossbones+   -  Reputation: 2505

Like
0Likes
Like

Posted 09 December 2013 - 08:42 PM

L. Spiro

I was indeed misusing the terms here.

About the input state being passed instead of the owning engine, in my scheme it is supposed to be bundled in the first item of the list or added as misc info.

In regard of a reference to the object I didn't mean it as a direct pointer or anything like it. But turning the input into an entity component can be useful sometimes like when you want games like, for an example, Chain Gang Chase, where you have several entities with independent controls. Of course an entity component isn't the only solution to create this abstraction layer. I just like the idea of component since that is the one I have the most experience with.

To show this is not something I made up, I'll quote a book (that maybe you consider a bad one).

Game Coding Complete 4th ed (page 243)Map Controls Directly to Controlled Objects
Don’t add parameters to distinguish between multiple joysticks or gamepads. A better solution is to create controls that map directly to the object they are controlling. For example, if multiple gamepads control multiple human drivers, the control code shouldn’t need to be aware of any other driver but the one it is controlling. You could set all this up in a factory that creates the driver and the controller and informs the input device code where to send the input from each gamepad.

Just to clarify, by driver the author means someone that drives a car, the context here is a racing game.

Yes, the interpreting of the input log should be done by a higher level-class that knows the game rules (including physics) or else it couldn't even define any actions. I still can't see what's so terrible about reusing the events in a list/stack as the log. I usually simply move the event from the event queue into another list that I interpret as a log. What's so wrong with this approach?

About applying the action immediately, it is probably necessary on some contexts. I couldn't even say that for sure since I have never got my hands on working on anything that applying the action later on the frame would affect it, but you clearly is years ahead of me. In my currently active projects (none professional, I'm actually an engineer) I apply any players actions just the same way I do with AI actions and at the same time during the frame. But this happens after all input has been remapped into an action and all actions have been interpreted and listed.

I must put a disclaimer here. Even though I have already done some context sensitive input, gestures and chords, I have never worked on any games that had fancy input systems like Tekken or any that needed top notch response time.

Edited by dejaime, 11 December 2013 - 08:19 PM.

### #16haegarr  Crossbones+   -  Reputation: 2997

Like
0Likes
Like

Posted 10 December 2013 - 03:30 AM

[I'm following this thread (and its companions, thanks especially to L. Spiro) with great interest, because my attempt to implement an input system will start soon next year…]

Components (in the meaning as part of a CES) are in my understanding a collection of elements to be plugged into appropriate sub-systems to have an effect. They are collected by entity, yes, but functionally they belong to sub-systems, and hence perhaps also to a higher level sub-system as understood as "game-object".

A Controller component (as a component that interprets user input to steer a player character) is obviously somehow connected to the input sub-system. As I have already introduced in a subtle way ;) it seems me that the component fits well as input interpreter into L. Spiro's input architecture: It looks at the translated and enqueued input, detects suitable input, and maps them into actions.

The question now is: Are those actions some that just should take place (i.e. the player requests them regardless whether the current in-game situation makes them possible), or else are they already fitted to the current situation, so that unfeasible actions are not created by the interpreter? How must a context look like to suppress any unfeasible actions?

There is another sub-system, namely the animation services, that comes into mind. Let's use Unity's Mecanim as an example. To have control over which action may be taken, the animation system utilizes a kind of state machine (letting layering and animation blend trees aside here). A transition from one state to another can be triggered externally. IMHO those triggers can (and need) be given by the actions from input interpretation. Such a method allows for changing the effect of actions, because the same "logical action" on the input side can trigger different state transitions in dependence on what state is currently active.

As such the input interpreter can cause a transition if and only if the current state has a suitably tagged transition, regardless whether the input interpreter actually checks whether an action is currently suitable. On the other hand, the triggers from the current state can be isolated and used as time variant table of allowed actions, so that the input interpreter already suppresses not allowed actions, but one has to deal eventually with table changes during interpreting an input sequence is still in progress. ATM it seems me that such action filtering at input interpreter level is not worth the closer coupling.

So I see 2 layers here: The Controller component that can be chosen and plugged into the input services as input interpreter, and the Animation component that defines what actions are feasible at any time. Maybe I'm violating one of L. Spiro's principles; if so, let be read about it …

Edited by haegarr, 10 December 2013 - 05:02 AM.

### #17SonicD007  Members   -  Reputation: 453

Like
0Likes
Like

Posted 29 December 2013 - 02:30 PM

I haven't had the time to mess with my project because of finals and it's the busy season at work, but I still need to implement input somehow in my game.  Right now this is holding me back from doing anything else (well mentally it's holding me back because I really want to get input to my game character so I can then implement collision and render my map with the player)

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

PARTNERS