keyboard input, C++

Started by
7 comments, last by Anri 19 years, 1 month ago
I am using GetAsyncKeyState() to check for keypresses. My question is how do I check for different key presses without running more than one GetAsyncKeyState() function? The way I have it set up now is:

while ( 1 ) {
   if ( GetAsyncKeyState( 0x61 ) )
      do_something;
   
   if ( GetAsyncKeyState( 0x62 ) )
      do_something_else;
}


I guess I could also do something like:
char ch;

if ( kbhit() )
   ch = getch();


And then use a switch statement. I remember at gametutorials.com they used something like HANDLE hinput; but I can't remember anything more than that. Is this way (using a HANDLE) better? If so, how do I implement it? Or should I just stick with GetAsyncKeyState(), or kbhit(), getch() and a switch statement? I'm trying to make an ASCII text based shooter in console mode. I can already foresee some difficulties with moving and shooting at the same time. If anyone knows how to head that kind of problem off, a heads up would be much appreciated. [Edited by - skulldrudgery on March 31, 2005 6:32:47 PM]
skulldrudgery--A tricky bit of toil
Advertisement
I believe you're looking for this which will get you an array that stores the state of EVERY key.

Hope I helped.
What type of parameter am I supposed to pass to it?

This is what I got:
#include <iostream>#include <conio.h>#include <windows.h>using namespace std;int main(){   char c;      while ( 1 ) {            if ( GetKeyboardState() )         c = getch();   }      cout << c << endl;      system( "pause" );   )
What is a PBYTE? [google] tells me it is a pointer to a byte. So, what pointer to which byte do I have to pass to the function?
skulldrudgery--A tricky bit of toil
If you look at the linked page you will see:

Quote:
Parameters

lpKeyState
[in] Pointer to the 256-byte array that receives the status data for each virtual key.


Thus, the function expects a pointer to an array of 256 bytes. It will store the key state info in that array, and return an indication of success or failure (which you will probably not worry about). So what you need to do is create some 256 byte buffer somewhere in your program, and pass it each time you want to check the key states.

Later on you will see:

Quote:
When the function returns, each member of the array pointed to by the lpKeyState parameter contains status data for a virtual key. If the high-order bit is 1, the key is down; otherwise, it is up. If the key is a toggle key, for example CAPS LOCK, then the low-order bit is 1 when the key is toggled and is 0 if the key is untoggled. The low-order bit is meaningless for non-toggle keys. A toggle key is said to be toggled when it is turned on. A toggle key's indicator light (if any) on the keyboard will be on when the key is toggled, and off when the key is untoggled.


This tells how to interpret the contents of the buffer after making the GetKeyboardState() call. You index the array with the virtual key code corresponding to the key you care about, yielding an element of the array of bytes, which therefore is a byte. Then you test its high-order bit (bitwise AND with 128) to see if the key is down.
Doh, I have to make a PBYTE myself! Ok this compiles fine, but how am I supposed to use it to get the keypress. It doesn't seem to work the way I'm doing it.

char c;PBYTE buffer_like_Zahlman_suggested;while ( 1 ) {         if ( GetKeyboardState( buffer_like_Zahlman_suggested ) ) {      c = getch();      break;   }      }   cout << c << endl;


EDIT: Maybe I'm getting in a little over my head with this GetKeyboardState() setup. I just want to get some keyboard input. Maybe some advice on one of the other methods I mentioned?
skulldrudgery--A tricky bit of toil
Quote:Original post by skulldrudgery
Doh, I have to make a PBYTE myself! Ok this compiles fine, but how am I supposed to use it to get the keypress. It doesn't seem to work the way I'm doing it.

*** Source Snippet Removed ***

EDIT: Maybe I'm getting in a little over my head with this GetKeyboardState() setup. I just want to get some keyboard input. Maybe some advice on one of the other methods I mentioned?


A PBYTE is just a pointer, which is a nice convenient thing for passing to functions, but it has to point at memory that belongs to you before you can do anything useful with it.

The simplest way in this case is to have an actual array allocation:

char keyData[256];// An array name can be used as a pointer to the beginning of the array:GetKeyboardState(keyData);// Now *examine* the data in keyData:if (keyData[VK_SPACE] & 128) {  // space was hit.}


If you are using the standard library containers, you should be aware that the storage space of std::vector is guaranteed to be a single chunk, which you can use as an array:

std::vector<char> keyData(256);// This isn't an array, but we can use its overloaded operator[] to access the// first element, and then get its address, which is a pointer:GetKeyBoardState(&keyData[0]);// etc.


Mixing this API with getch() is simply not a good idea - each will make its own attempt to read the keyboard, and something is bound to get messed up. They certainly won't make use of the same reading. Also, getch() works fundamentally on a higher level; it is not really checking key states, but instead waiting for the next character to arrive - after the OS has done all the work of translating keypress durations into "character input" events. It's really more like working with cin, except that it isn't line-buffered.

Like I said:

Quote:
This tells how to interpret the contents of the buffer after making the GetKeyboardState() call. You index the array with the virtual key code corresponding to the key you care about, yielding an element of the array of bytes, which therefore is a byte. Then you test its high-order bit (bitwise AND with 128) to see if the key is down.
I don't know Zahlman, it doesn't seem to work. I just want to get some key input. I'll just go with one of the other methods. Any suggestions for moving and shooting at the same time?
skulldrudgery--A tricky bit of toil
If you are more concerned about making the game than about performance, all GetKeyboardState will earn you is:

if(buffer[VK_LEFT]) MoveLeft();

rather than

if(GetAsyncKeyState(VK_LEFT)) MoveLeft();

There's nothing really wrong with calling GetAsyncKeyState multiple times as far as I know.
What I do is create a global definition of a custom structure containing a load of boolean variables...

struct TYP_KEYBOARD_BUFFER
{
bool Arrow_Up;
bool Arrow_Down;
bool Arrow_Left;
bool Arrow_Right;
bool Escape;
}

TYP_KEYBOARD_BUFFER sKeyboardBuffer;

...then, I make a function to reset this structure...

void KEYBOARD_reset_buffer(void)
{
sKeyboardBuffer.Arrow_Up = FALSE;
sKeyboardBuffer.Arrow_Down = FALSE;
...
...
...
}

...then, when the logic is performed for my game, I first call a function to gather input from the keyboard and store it into this buffer( but make sure you call the previous function to reset the structure so that all the keys aren't pressed! )...

////////////////////////////////////////////////////////////////////////////////
int KEYBOARD_retreive_input(void)
{
// Reset the Keyboard buffer before obtaining the input...
KEYBOARD_reset_buffer();

// pKeyboard is simply a DirectInput device, of course...
if(!pKeyboard)
{
// No Keyboard? Log error and return with failure.
return FALSE;
}

char buffer[256];
HRESULT hr;

hr = pKeyboard->GetDeviceState(sizeof(buffer), (LPVOID)&buffer);

if( hr != DI_OK )
{
// Do error checking here...
return FALSE;
}

// Now fill up the Keyboard Buffer structure...Yawn.


// The Escape key...
if (KEYDOWN(buffer, DIK_ESCAPE))
{
sKeyboardBuffer.Escape = TRUE;
}

// The Arrow keys...
if (KEYDOWN(buffer, DIK_DOWN))
{
sKeyboardBuffer.Arrow_Down = TRUE;
}

if (KEYDOWN(buffer, DIK_UP))
{
sKeyboardBuffer.Arrow_Up = TRUE;
}
......
......
......
}

/////////////////////////////////////////////////////////////////////////////

...and so, after you have the input from the keyboard, you can do the logic. If you want to exit the program by pressing the Esc key...

if(sKeyboardBuffer.Escape == TRUE)
{
// the escape key has been pressed - call a function to quit the program...
PROGRAM_send_quit_message();
}

...hope this helps! ^_^

Languages; C, Java. Platforms: Android, Oculus Go, ZX Spectrum, Megadrive.

Website: Mega-Gen Garage

This topic is closed to new replies.

Advertisement