Sign in to follow this  
josiahpeters

GLFW Keypress Question - should I fire events to manipulate an object or set the object's state?

Recommended Posts

Hey everyone, this is my first post after lurking and reading for a while. I am a web programmer and started learning graphics / game programming with C# and XNA a while ago. I have never released anything but have made a few useless "tech demos." I have been learning C++ recently and decided to tackle making a little game with Open GL. I am using GLFW as my window library and things have been going relatively smoothly thus far.

My question is about how I am handling input. Right now I fire an event to my character system telling it to move the character every time a keypress is detected. This works great for one key being held down. It also works for two keys being held down. However once I let go of the second key while the first key is still held down, GLFW stops calling back my keypress call back function each frame until I let go of the key that is held down.

Example:

[u]0 seconds - [/u]
Hold W key to
start walking forward
keypress function is called back,
w has a value of 1

[u]5 seconds[/u] -
W key is still held down
still walking forward
keypress function is called back,
w has a value of 1

[u]10 seconds- [/u]
W key is still down, now hold Left Shift Key down
still walking forward, but now at 2x speed because of the shift key being down
keypress function is called back
w has value of 1, shift has value of 1

[u]15 seconds - [/u]
W key is still down, let go of the shift key -
no longer moving forward
keypress function is called back
w has value of 1, shift has value of 0 - indicating key was let go

[u]15.1 seconds [/u]
W key has been down the whole time
no movement since letting go of the shift key
no callbacks on my keypress function

[u]20 seconds [/u]
W key has been down the whole time
no movement since letting go of the shift key
no callbacks on my keypress function

25 seconds
let go of W key
keypress function is called back
w key has a value of 0 - indicating key was let go

Below is some code from my callback function that GLFW calls on a keypress:

[code]

void GLFWCALL OnKeyPress(int key, int action)
{

if(glfwGetKey(GLFW_KEY_LSHIFT) )
{
eventData data(eventType::CHAR_SPRINT, moveableCharacter);
EventSystem->TriggerEvent(eventType::CHAR_SPRINT, &data);
}

if(glfwGetKey('W') )
{
eventData data(eventType::CHAR_FORWARD, moveableCharacter);
EventSystem->TriggerEvent(eventType::CHAR_FORWARD, &data);
}
// ... more of the same
}[/code]


First, is this how GLFW is supposed to work and am I going about this all wrong? Should I be manipulating the character through triggering events or should I have a character state that gets altered by the events such as WALKING, IDLE, RUNNING, etc... Or, is this a bug in GLFW?


TLDR: GLFW reports a keypress event for the W key each frame it is held down until I press a second key while still holding W down. A keypress event is reported when I let go of the key but nothing happens in between.

Thanks for looking at this!

Share this post


Link to post
Share on other sites
[quote name='ApochPiQ' timestamp='1310423590' post='4834030']
Check out [url="http://www.gamedev.net/blog/355/entry-2250186-designing-a-robust-input-handling-system-for-games/"]this article[/url] if you haven't already run across it.
[/quote]

I had not seen this yet, thanks!

*EDIT*

So I decided to do a few things differently. First of all I was coding my input callback all wrong.

Before I was calling glfwGetKey(GLFW_KEY_LSHIFT) inside of each key callback, see below:

[code]

void GLFWCALL OnKeyPress(int key, int action)
{
if(glfwGetKey('W') )
{
eventData data(eventType::CHARACTER_MOVE, moveableCharacter);
EventSystem->TriggerEvent(eventType::CHARACTER_MOVE, &data);
}
}
[/code]

Instead of looking up the key in the call back like I was doing, I am now using the key code provided by the callback, as below:
[code]

void GLFWCALL OnKeyPress(int key, int action)
{

switch(key)
{
case GLFW_KEY_SPACE:
state = JUMPING;
stateOn = action;
break;
case GLFW_KEY_LSHIFT:
state = SPRINTING;
stateOn = action;
break;
case 'W':
state = MOVE_FORWARD;
stateOn = action;
break;
case 'S':
state = MOVE_BACKWARD;
stateOn = action;
break;
case 'A':
state = MOVE_LEFT;
stateOn = action;
break;
case 'D':
state = MOVE_RIGHT;
stateOn = action;
break;
}
}
[/code]

That article helped me wrap my head around not having the input system drive my character directly. There was a little too much typing to do to implement their system, so I went with a simpler approach. On each keypress I pass a character state and a bool value of whether the state is on or off. This gets fired as a MOVE_CHARACTER event. My character system then updates the state for the character, turning on or off different states.

Meanwhile my update statement reads the various states and whether they are on or off and does the moving of the character depending on the states. This means I can be jumping, sprinting, moving forward and strafing left all at the same time.

I still intend on following through with reading character mappings from a file and mapping them to various actions, I'm just not there yet. That article was very useful, thanks for that again!

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