Advertisement

direct input keyboard repeat rate

Started by September 21, 2000 04:22 PM
12 comments, last by DiscoStoo 24 years, 3 months ago
I am currently working on a tile-based game, and I''ve finished most of it as of now, but I''m having a problem with Direct Input repeat rate. The main board is made up of 32x32 pixel tiles, so when the user presses the appropriate key, the player moves 32 pixels in whatever direction. The problem is that Direct Input reads the input soooo fast, the player jumps across the screen at a single tap of the button. I have tried having a timer set when a key is pressed, and moving the player when the timer is up, but that didn''t work too well. I know there must be a function or something out there that will help me, (people write tile-based games all the time, right?) but I can''t seem to find anything. ------------------------------------------------------------ He wants a shoehorn, the kind with teeth, because he knows there's no such thing.
------------------------------------------------------------He wants a shoehorn, the kind with teeth, because he knows there's no such thing.
This is fairly easy to solve by using 2 methods, depending on your preferences, I recommend the first method.

1. Have a flag for the key, or just a single general key flag. It works as so: when the a keyboard key is pressed, the first time it sees it is pressed the key flag is set to true and the action that key does is executed. Then durning the next game loop which is only a fraction of a second later and the key will still be down, but you have the check against the key flag, if the key flag is true you do nothing cause the key action was already done. Then when the key is let go you have the keyup check and in there you set the key flag back to false.

2. Or you just execute the key action when they keyup is encountered.

Possibility
Advertisement
this got me once too along time ago, let me see if I could remember what I came up with..

while the keyisup
if keydown
execute scroll function

I think this was what I came up with as a "Key Press" method.

let me know how it turn out, been awhile!
The point here is to move the character at a specified speed if the key is held down, not a set number of pixels on each key down event.

Each frame, you check if the key is currently down. If so, you move the character according to this equation

  ElapsedTime = time in seconds since last frame  CharacterSpeed = how many pixels per second to move the character  Delta = CharacterSpeed * ElapsedTime; 


If you game is running at 30 frames per second, then ElapsedTime will be 1.0/30 or 0.03333. Say you want the character to move at 16 pixels/second. This gives us

  Delta = 16 * 0.03333        = 0.53328 


That is how far our character has moved in 1/30th of a second. Now add this value to the character''s current position. If the character is moving east (positive X), then

  Character.X += Delta; 


Note that this will require the X variable to be a floating point variable. When you actually go to draw the character, pass the rounded value of X and Y to the blit routine.

If you get a bit more complex, you can specify a direction angle and use sin and cos in your equation to move the at the given speed at any angle.



Steve 'Sly' Williams
Tools Developer
Krome Studios
Steve 'Sly' Williams  Monkey Wrangler  Krome Studios
turbo game development with Borland compilers
quote: Original post by DiscoStoo

I am currently working on a tile-based game, and I''ve finished most of it as of now, but I''m having a problem with Direct Input
repeat rate. The main board is made up of 32x32 pixel tiles, so when the user presses the appropriate key, the player moves 32 pixels in whatever direction. The problem is that Direct Input reads the input soooo fast, the player jumps across the screen at a single tap of the button.

I have tried having a timer set when a key is pressed, and moving the player when the timer is up, but that didn''t work too well. I know there must be a function or something out there that will help me, (people write tile-based games all the time, right?) but I can''t seem to find anything.

------------------------------------------------------------
He wants a shoehorn, the kind with teeth, because he knows there''s no such thing.




What I use is the following:

Setup an array of long integers for your keys. When a key is pressed:

if (keys[KEY_PRESSED] - GetTickCount() >= REPEAT_TICK_VALUE)
{
// then we do whatever for that key press event
keys[KEY_PRESSED] = GetTickCount(); // reset the time for that key
}

If the first IF fails, then we know we shouldn''t do anything because the key was just pressed recently. You could even setup an array of REPEAT_TICK values for all the different keys. You might want ''backspace'' to repeat faster than ''A'' and such.

This is probably far from the quickest way of doing things, but it is easy to understand and use.
Okay, I''ve never tried this, but you could:

// let player move the object
// allow player to move
if (keyboard_state[DIK_RIGHT])
bat.x+=8;
Sleep(500);
bat.x+=8;
Sleep(500);
bat.x+=8;
Sleep(500);
bat.x+=8;
Sleep(500);
else
if (keyboard_state[DIK_LEFT])
bat.x-=8;
Sleep(500);
bat.x-=8;
Sleep(500);
bat.x-=8;
Sleep(500);
bat.x-=8;
Sleep(500);

if (keyboard_state[DIK_UP])
bat.y-=8;
Sleep(500);
bat.y-=8;
Sleep(500);
bat.y-=8;
Sleep(500);
bat.y-=8;
Sleep(500);
else
if (keyboard_state[DIK_DOWN])
bat.y+=8;
Sleep(500);
bat.y+=8;
Sleep(500);
bat.y+=8;
Sleep(500);
bat.y+=8;
Sleep(500);


Sincerely,
Jonathan
A.K.A. -- Fourth Horseman
Sincerely,JonathanA.K.A. -- Fourth Horseman
Advertisement
quote: Original post by DiscoStoo

when the user presses the appropriate key, the player moves 32 pixels in whatever direction. The problem is that Direct Input reads the input soooo fast, the player jumps across the screen at a single tap of the button.


Are you retrieving buffered data or immediate data? According to Microsoft, "Buffered data is a record of events that are stored until an application retrieves them. Immediate data is a snapshot of the current state of a device."

If using buffered data, it depends on the repeat rate of the keyboard. You can set the keyboard data buffer size to 1 so it will hold only one keystroke between calls to the GetDeviceData method (which retrieves the data).

There's an excellent suggestion above to just check the key state every frame. However, if you need to process frames (i.e. animated tiles) faster then the player should move, you should just add a counter that won't check the state of the keyboard until a certain number is reached. Say you wanted the player to move once every 3 frames of animation. Just do:

GameMain ()
{
static int iCounter = 0 ;

DrawFrame () ;
iCounter++
if (iCounter == 3)
{
DirectInputDevice.GetDeviceState () ;
iCounter = 0 ;
/* etc., etc. */
}
}

Personally, I prefer buffered data for turn-based tile games, and immediate data for real time games.

Edited by - Steel on September 25, 2000 10:11:57 PM

Edited by - Steel on September 25, 2000 10:13:05 PM
I don''t know if anyone''s said this yet but here''s what I would do (have done). In my game, I had a menu with an arrow next to it, and when I''d hit the arrow key to move down a selection, it''d go flying 3 or 4 selections just from a tap, similar to your prob. Here''s how I fixed it (thanx to Mr. Bunnies on #gamedev for helping me out on this one):
UCHAR keyboard_state[256]; // keyboard state tableUCHAR old_keys[256];       // keep track of previously pressed keys......// Get keyboard device stateif (LPDIkey->GetDeviceState(256, (LPVOID)keyboard_state) != DI_OK)	return FALSE;memcpy (old_keys, keyboard_state, sizeof(char[256]));...// Now test input// When you want to test if a key has been pressed ONCE, do this// This example tests the space barif (!(keyboard_state[DIK_SPACE]) && old_keys[DIK_SPACE]) {    // Do space bar code} 


I hope this helps you out, if it has nothing to do with what you''re doing, then forget everything I just typed




"We are the music makers, and the dreamers of the dreams."
- Willy Wonka
quote: Original post by Steel

There''s an excellent suggestion above to just check the key state every frame. However, if you need to process frames (i.e. animated tiles) faster then the player should move, you should just add a counter that won''t check the state of the keyboard until a certain number is reached. Say you wanted the player to move once every 3 frames of animation. Just do:

Personally, I prefer buffered data for turn-based tile games, and immediate data for real time games.



Good idea bad idea. Checking against the framerate is a bad thing. If I run at 50FPS and you run at 20FPS, my reaction times and movements will be much better than yours.

But as you say, buffered is good for turn based stuff, and immediate is good for real time stuff. Depends on the game.

"Five passengers set sail that day, for a three hour tour, a three hour tour...."
Oh yeh, whatever you decide to do, I wouldn''t recommend using Sleep(), Nothing against The Fourth Horseman, but I don''t thing that would be a good approach, not good programming practice. For a quick fix to test something, sure, but for a long term in the final version kinda thing, no.

This topic is closed to new replies.

Advertisement