View Full Version : Keyboard input
Muffinking
2002.06.14, 12:17 PM
When I was writing my old game engine I was using the apple event manager to record keyDown events to get my input but that was really really slow.
I never fully understood how to use GetKeys() to check for keyboard input so i never used it. But now that I am developing on OS X(Carbon) I would like to use GetKeys() or something like it for my keyboard input.
My game will have a hybrid of mouse and keyboard input to play.
is there a resource somewhere or a tutorial on using GetKeys()? cause I really want to know how to use it. from what I hear it is much faster than the high level event managers.
any help would be great. sample code welcome.
Hank-
OneSadCookie
2002.06.14, 11:11 PM
This discussion came up in depth on the old boards; you might still be able to find it there.
Basically, all the advantages belong to the event-based approach. If you want to poll, you can just store the state of the key in your own array when you receive the event.
As to speed, the only thing that affects the speed is how often you check. With polling, you risk missing a key press and release if you don't check often enough, where you'll always see it if you're getting events.
If after all my persuasion you still want to use GetKeys, the basic idea is that the array you get back is a bit array, it just happens to be stored as an integer array. The index into the bit array is the key code. That means if you want to check key code 88, you have to figure out which integer in the array to look in (probably the third), and which bit of that integer (probably either 24 or 8 if i did the subtraction right). Somebody can probably provide the exact code though :)
RedWolf
2002.06.15, 01:10 AM
Here is a method I use in one of my classes:
/* ================================================
* isPressed()
*
* Check if a particular key is currently being pressed.
*
* parameter
* k = any keyboard scan code, 0-127
* ================================================ */
int Game::isPressed(unsigned short k)
{
KeyMap keymap;
::GetKeys(keymap);
return ((keymap[k>>5] >> (k & 7)) & 1);
}
For example, I call this as follows:
#define L_OPTION_KEY_SC 0x3A /* 58 (See IM: I-251) */
if (Game::isPressed(L_OPTION_KEY_SC))
Game::showLastMove();
I'm using GetKeys() for my keyboard input.
I adopted the code from the iGetKeys example which you can find at the Apple Developer connection.
http://developer.apple.com/samplecode
You may wonder why it's a lot of code. Well, that is because you must convert the key codes to char codes yourself using the systems 'KCHR' resource. Otherwise the mapping of the keys might be wrong on keyboards for different languages.
For example, the Z and Y keys are swapped on German keyboards. So you would think Y is down when Z is pressed.
Everything you need for this is in the sample code.
And GetKeys() isn't slow. It should as fast as event polling or even faster. And missing a keystroke is nearly impossible.
-Tobi
OneSadCookie
2002.06.17, 01:14 AM
Originally posted by Tobi
And missing a keystroke is nearly impossible.
That depends entirely on how often you're checking. At 20 or 30Hz it's perfectly possible. With events, it's actually impossible.
If your isPressed function looks like the one posted above, the overhead in calling GetKeys for each key you want to check may well become significant. In that respect, events protect you from your own stupidity :)
My method is checking the keyboard state about 50 times a second, so 50 Hz. If it really happens that a key stroke is lost, the user/player has very fast fingers :)
I have bad experiences with keyboard events (on Classic, perhaps it's perfect on Carbon now). Like, if I hit multiple keys at the same time only one/a few of them will create an event, so I would loose some. This is bad for games as there are often a lot of keystrokes at the same time especially if two players share the same keyboard.
If this isn't a problem anymore, I would encourage you to use events instead of course.
-Tobi
OneSadCookie
2002.06.17, 06:17 AM
I've never seen that with Carbon's raw key events...
kainsin
2002.06.17, 01:18 PM
Bah, GetKeys()....:P
I'd use OneSadCookie's suggestion.
typedef struct {
bool upKeyPressed;
bool downKeyPressed;
bool leftKeyPressed;
bool rightKeyPressed;
} KeyStatus;
KeyStatus gKeyStatus;
[...]
WaitNextEvent( ... );
switch( theEvent )
{
case keyDown:
// Check to see if it is one of the directional keys and
// set the correct field in gKeyStatus to true.
case keyUp:
// Check to see if it is one of the directional keys and
// set the correct field in gKeyStatus to false.
[...]
}
Then just check the correct field in gKeyStatus to see if the key is being pressed. Of couse, don't forget that keyUp events are turned off by default and you'll need to turn them on when you start up your application.
RedWolf
2002.06.18, 12:14 AM
Originally posted by OneSadCookie
> If your isPressed function looks like the one posted above,
> the overhead in calling GetKeys for each key you want to
> check may well become significant. In that respect, events
> protect you from your own stupidity
I only use isPressed() in a few situations and only check one key. I wouldn't recommend it for general keyboard input processing. I use the standard keyboard events for that.
Codemattic
2002.06.18, 02:05 PM
My understanding of the problems associated with GetKeys is that some users will have problems with your game. Most will be ok - but there are some configurations out there that wont work. The keymap is different with some keyboards - and keyboards like those split ones that are supposed to reduce r.s.i. wont work. The problem with the split ones is that they are registered as two seperate devices - and GetKeys only returns the keymap of the last keyboard device that had a keypress.
Ive never independantly verified this - and the number of people who couldnt play your game is probably pretty small - but f.y.i.
cheers,
Codemattic
vBulletin® v3.8.4, Copyright ©2000-2010, Jelsoft Enterprises Ltd.