Sign in to follow this  
rmetzger

How can I get keyboard input in a slower, controlled manner using direct input 8?

Recommended Posts

rmetzger    100
Hello,

I am making a tetris game and am getting input from the keyboard using direct input 8. When I press a key, it reads multiple inputs for that key, even if I tap it quickly. So my tetris blocks go zooming back and forth when I tap an arrow key. I would like to process the keyboard input in a controlled manner.

In the function where I process input I do this:

// Global
LPDIRECTINPUTDEVICE8 m_diKeyboardDevice;
BYTE m_keys[256];

// Called every frame
void ProcessInput ()
{
HRESULT hr = m_diKeyboardDevice->GetDeviceState( sizeof(m_keys), m_keys );

if (m_keys[DIK_ESCAPE] & 0x80)
{
exit (4);
}
if (m_keys[DIK_RIGHT] & 0x80)
{
// do something here
}
}

I tried using a timer that only called ProcessInput every 0.1 seconds. That worked for the most part, but every so often, 2 key presses are read when I hit the key once. Can someone please enlighten me on a better way to accomplish this?

Thanks!

Share this post


Link to post
Share on other sites
Buckeye    10747
You'll need a toggle. That is, when the key is pressed, set a flag (e.g., "keyRightDown"). Ignore any further input from DIK_RIGHT until the key is no longer pushed (and you clear "keyRightDown"), or until a clock times out, whichever you prefer.

You can use individual flags for your "important" keys, or keep an array of counts for each key. When a key is pressed, set the appropriate array member to some count which you decrement regularly. Unless the count for a key is zero, ignore it.

Share this post


Link to post
Share on other sites
monkeyboi    188
Use a global variable or whatever as delay time
pseudo as below

int delay = 0;
if (m_keys[DIK_ESCAPE] & 0x80)
{
exit (4);
}
if (m_keys[DIK_RIGHT] & 0x80)
{
if(delay==0){
// do something here
delay = 50;//calculate actual time
}
}
delay--;
if(delay<0)
delay = 0;


Share this post


Link to post
Share on other sites
rmetzger    100
Quote:
Original post by Evil Steve
Quote:
Original post by no such user
Or just process the WM_KEYDOWN window message instead.
This, definitely.


I was handling all my direct input code from my tetris.cpp and not my main.cpp where my windows code is located. With direct input I could just view the state of the keyboard whenever I wanted which was every .1 seconds. But for the WM_KEYDOWN, windows sends that message when it happens right? So how do I check which keys are down when I need to check it and not necessarily when windows sends the message?

Share this post


Link to post
Share on other sites
rmetzger    100
Also, since I was only checking the keyboard state ever 0.1 seconds and re-setting the timer after getting the keyboard state, how would it be possible that a key could be pressed twice? A key can only be up or down, so how could it be down 2 times from checking the keyboard state once?

Share this post


Link to post
Share on other sites
Buckeye    10747
Quote:
A key can only be up or down, so how could it be down 2 times from checking the keyboard state once?

Not sure what you mean by "once." If you're checking whether it's up/down every 0.1 seconds, it may very well be down for longer than 0.1 seconds. It doesn't change state just because you check the state.
Quote:
So how do I check which keys are down when I need to check it and not necessarily when windows sends the message?


case WM_KEYDOWN:
keyArray[wParam] = true;
break;
case WM_KEYUP:
keyArray[wParam] = false;
break;

Are you concerned that you need to see a key up in less time than it takes to check for messages? If so, try it and see if there's a problem.

Share this post


Link to post
Share on other sites
rmetzger    100
Quote:
Original post by Buckeye
Quote:
A key can only be up or down, so how could it be down 2 times from checking the keyboard state once?

Not sure what you mean by "once." If you're checking whether it's up/down every 0.1 seconds, it may very well be down for longer than 0.1 seconds.

What I mean is when my timer gets to 0.1 sec, I check what keys are down and reset the timer to 0. If a certain key is down, I move the tetris block. So when I check the keyboard state and find the key is down, it is supposed to call the function to move the piece once. Somehow it is happening twice in an instant instead of 0.1 seconds apart. It seems to happen for only 25% of key presses.

Maybe i'm just going about processing the input wrong. I'm up for suggestions :-)

Share this post


Link to post
Share on other sites
Buckeye    10747
Quote:
Somehow it is happening twice in an instant instead of 0.1 seconds apart.

How did you determine that?

Can you post the actual code for ProcessInput (versus "//do something here"), and the code where ProcessInput is called?

Share this post


Link to post
Share on other sites
SiCrane    11839
Quote:
Original post by rmetzger
What I mean is when my timer gets to 0.1 sec, I check what keys are down and reset the timer to 0. If a certain key is down, I move the tetris block. So when I check the keyboard state and find the key is down, it is supposed to call the function to move the piece once. Somehow it is happening twice in an instant instead of 0.1 seconds apart. It seems to happen for only 25% of key presses.


This sounds like a horribly cumbersome method to process your blocks. Why not just move the block once when a key press comes?

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