Sign in to follow this  

Slowing down the key events

This topic is 4861 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello All, I am working on learning OpenGL and I am coding a classic style RPG, Similar to the old NES ones. I am having a problem with using the arror keys. I would like the arrow keys to move my background by one tile per keystroak, but I also want to be able to hold the key down and have it move smoothly. Currently the keys move the background way too fast. Is there a way to force it to wait a set time before repeating the key event when the key is held down? Any help is greatly appriciated. SweetJ PS. my key code is below void Keyboard_Input() // Keyboard input { if(GetKeyState(VK_UP) & 0x800) { MapY -= .25; } if(GetKeyState(VK_DOWN) & 0x800) { MapY += .25; } if(GetKeyState(VK_LEFT) & 0x800) { MapX += .25; } if(GetKeyState(VK_RIGHT) & 0x800) { MapX -= .25; } }

Share this post


Link to post
Share on other sites
The events always happen when the happen, so you have to change the way your program responds to the events. What you do is- keep excepting the events but when you have the player move, start a timer going for the amount of time it should take to move one space. When you get any keypress events, have your program check the timer. If the timer is still counting up, the program does nothing. If the timer is already beyond the target time, then allow the player to move again and restart your timer.

Share this post


Link to post
Share on other sites
what you need is some way of mintoring the state changes
rather than the actual state

ie. only move the map up/left/right/down if the LAST keyboard
state was DOWN and the CURRENT state is up (ie. Key was pressed and then released)

hope you see what i mean, a sample implementation (off the top
of my head, so it might not work :)

definitions:

enum {
KEY_UP = 0,
KEY_DOWN,
KEY_LEFT,
KEY_RIGHT,
};

struct keyState
{
int lastState[4]; // can only be set to 1 or 0
int currState[4]; // can only be set to 1 or 0
} keyboard;





implementation:

void keyboardPreStateChange()
{
int i=0;
keyState *kb = keyboard[keyId];

// move currState to lastState
for(i=0; i<4; i++) {
kb->lastState[i] = kb->currState[i];
kb->currState[i] = 0;
}
}

int keyboardKeyUp( int keyId )
{
keyState *kb = keyboard[keyId];
if( kb->lastState[keyId] && !kb->currState[keyId] )
return 1;
else {
return 0;
}
}

void keyboardUpdate()
{
#define UPDATE_STATE(x) if(GetKeyState(VK_##x)&0x800) keyboard.currState[KEY_##x] = 1;

keyboardPreStateChange();

UPDATE_STATE( UP );
UPDATE_STATE( LEFT );
UPDATE_STATE( RIGHT );
UPDATE_STATE( DOWN );
}

void keyboardInput() // Keyboard input
{
keyboardUpdate();

if( keyboardKeyUp( KEY_UP ) ) {
// do something
}
// etc etc
}

Share this post


Link to post
Share on other sites
If I use the change of state method, wont that force the user to press and release the key for each step. If that is true it takes away the ability to hold the key down and move more then once. I think that would be really annoying since the player will be walking around most of the game.

I think the timer would still work better for what I need. Perhaps I am missing something.

Thanks,

SweetJ

Share this post


Link to post
Share on other sites
(edit: refering to silvermace's previous post)
Actually yes, the way that silvermace describes is better. If you use the timer, it may create annoying instances in which the program misses some input.

[Edited by - Kelly G on August 20, 2004 12:36:18 AM]

Share this post


Link to post
Share on other sites
the beauty of the state change system, is that its flexible

if you want to test that the user is holding down the key, its
simple:


if( keyboard.currState[key] && keyboard.lastState[key] )
movePlayer();


also, to make it 'wait' just have a counter that tracks how
long the key has been down, once the counter reaches X value,
continuously move the player and reset the counter when the key
is released

Share this post


Link to post
Share on other sites
Is there a way to still have the player move when they hold the key down? because otherwise they have to press and release the key for each step. If you needed to move to the other side of the map that would be difficult.

Thanks,
SweetJ

Share this post


Link to post
Share on other sites
Quote:
Original post by Kelly G
Actually yes, the way that silvermace describes is better. If you use the timer, it may create annoying instances in which the program misses some input.


I don't know what kind of timer, but if you were to use sleep, it seems to keep the keypresses in a buffer (at least it did when i was using conio.h to get the keypresses, cause i needed to wait 8 seconds between actions, and when you pressed the key while it was sleeping it would detect the keypress as soon as it returned.

Share this post


Link to post
Share on other sites
Of course, it depends on your setup, but if you are using something like NeHe's basecode you can add in a function pointer to optionally direct keyboard messages to directly from the WinProc. You would want to do this because windows automatically sends messages in the way that you requested (there are more WM_KEYDOWN messages than WM_KEYUP messages when a button is held down long enough). However, as the others have suggested, it's not too hard to implement this behaviour yourself.

Share this post


Link to post
Share on other sites
instead of using a fixed step, just move (Velocity * dt), where dt is the time it took for the last frame. Then you can poll key events as fast as they come, and the velocity of your character will remain the same on every PC.

e.g.

dt = NewTime - LastTime;
LastTime = NewTime;

if (bunch_of_stuff)
MapX += Vel * dt;
....
loop

Share this post


Link to post
Share on other sites

This topic is 4861 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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