Clearing keys after GetKeyState()

Started by
9 comments, last by Evil_Greven 18 years, 10 months ago
Hey. I'm using the GetKeyState() function in the Win32 API to poll the keyboard for keypresses. The thing about it is that it appears to "remain on" until another key is pressed. For example, in the pong clone I'm using it in, the paddle will go all the way to the top/bottom of the screen and stay there until another key is pressed. It seems to only get the last key pressed. I'm wondering which function to use to check for multiple key inputs at the same time and clear them when the key is lifted. What I'm doing right now is having a 256 boolean buffer that holds whether any of the keys have been pressed. I just poll the keyboard like this:

void KeyboardInput::PollKeyboard()
{
    short key_pressed;
    for ( unsigned int i = 0; i < 256; ++i )
    {
        key_pressed = GetKeyState(i);
        //WinToIICode() converts a Windows virtual keypress code to my own
        //sequential code.  Shouldn't affect anything - its just a big switch
        //statement that appears to be functioning properly.

        //keys[] is the 256 boolean buffer I mentioned earlier. 
        if (key_pressed<0)
        {
            keys[WinToIICode( i )] = true;
        }
        else
        {
            keys[WinToIICode( i )] = false;
        }
    }
}

On MSDN's keyboard input page they say that in general, you will use GetKeyState() for keyboard input, but it doesn't appear to be helping, unfortunately. Any hints? Thanks.
my siteGenius is 1% inspiration and 99% perspiration
Advertisement
Try GetAsyncKeyState perhaps?

Alternativly, process WM_KEYDOWN and WM_KEYUP events.
I'm trying to allow multiple keys being pressed at the same time. The game is two player as well as one player, and it wouldn't be very fair if you were playing pong and your friend prevented you from moving your paddle by pressing on their controls, would it? I tried both GetAsyncKeyState and GetKeyState, and neither of them really worked. Processing WM_KEYPRESS messages works for single-key input just fine, but I haven't found a way to get it to work for multiple simultaneous keypresses.
my siteGenius is 1% inspiration and 99% perspiration
How frequently do you call GetKeyboardState?
Quote:Alternativly, process WM_KEYDOWN and WM_KEYUP events.


Much better option than Get(Async)KeyState
Hrmmmn, I doubt you're using the function properly, silverphyre673.


Anyway, this method does basically what you want. Put this code in your WndProc function, and avoids those functions completly (I prefer this method):

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){    switch(message)    {    case WM_KEYDOWN:        keys[wParam] = true;        break;    case WM_KEYUP:        keys[wParam] = false;        break;    }}
Quote:Original post by Andrew Russell
Hrmmmn, I doubt you're using the function properly, silverphyre673.


Anyway, this method does basically what you want. Put this code in your WndProc function, and avoids those functions completly (I prefer this method):

*** Source Snippet Removed ***


Agreed. I tried your method, but it unfortuntely resulted in the original problem of not working when two keys are pressed at once (only the latest key pressed is treated as down). Also, does anyone know how to set how long it takes before holding down a key just creates a whole bunch of characters, like holding down "i" might produce iiiiiiiiiiiiii? I want the paddles to move smoothly, and its really hard to play right now at fast speeds. Thanks.
my siteGenius is 1% inspiration and 99% perspiration
Then something is wrong in the way you are using the keys[] array. Are you setting a key to false later in your program or something?

Unless you are doing something extreemly daft when you process the incoming keys (which is almost impossible with the WM_KEYDOWN/WM_KEYUP method I gave you).

The keyboard repeat-rate should be irrelevent. It sends another WM_KEYDOWN event before it ever sends a WM_KEYUP event. Meaning that the key is already set to true when the event does "keys[wParam] = true;" (in other words, it has no effect).

Your messages would be something like "DOWN(key becomes true) DOWN DOWN DOWN DOWN DOWN UP(key becomes false)".

Your function that reads the key array should look something like this:
void Update(){    if(keys[PLAYERONE_UP])    {        playerone.y += 5;    }    if(keys[PLAYERONE_DOWN])    {        playerone.y -= 5;    }    if(keys[PLAYERTWO_UP])    {        playertwo.y += 5;    }    if(keys[PLAYERTWO_DOWN])    {        playertwo.y -= 5;    }}
Ah! I got it. My fault: I was checking to see if a key was pressed with my input wrapper every message. Changing it to checking once every 10ms worked. Thanks!
my siteGenius is 1% inspiration and 99% perspiration
Wait... why does that make a difference? You're not doing a "has a key been pressed in the last 10ms" deal, are you??

This topic is closed to new replies.

Advertisement