Skip to main content
gamedev.net
🔒 Locked

Processing keystrokes

Started by stevek2k 8 replies 2.4k views
Original Post
stevek2k
stevek2k
Hi, i'm having a bit of trouble, hope someone can help me. I'm currently doing a piece of coursework for uni using Peter Walsh's zen game engine, c++ .net directx8, what i'm getting stuck on is trying to let the user change their control buttons in a game option menu. The question is, is there anyway (excluding event listening) to read a keypressed. As in if the letter 'a' is press there is a function i can do like char letterPressed = letterPressed(); obviously i don't care if its the int value returned or not because all it does is a compare later on. I've taken a look at stuff like getche() and all that but don't know if i'm coding it wrong or it just doesn't apply to this. any help is greatly appreicated
jollyjeffers
jollyjeffers
Are you wanting an answer in terms of your particular engine, or just a general answer?

Typically a windows-based game will use one of two ways to get keyboard entry:

1. Windows messages (WM_KEYPRESS etc..)

2. DirectInput

For the most part the former is simple and straightforward.

hth
Jack
<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ |
stevek2k
stevek2k
well a general answer, as long as it works really

currently the movement runs like this

bool PlayerMove(char direction[]) {
if (direction == "up") { if (keyboard_state[DIK_UP]) { return true; } else { return false; } }
else if (direction == "down") { if (keyboard_state[DIK_DOWN]) { return true; } else { return false; } }
else if (direction == "left") { if (keyboard_state[DIK_LEFT]) { return true; } else { return false; } }
else if (direction == "right") { if (keyboard_state[DIK_RIGHT]) { return true; } else { return false; } }
else { return false; }
}

but instead of having say keyboard_state[DIK_RIGHT], i would like

keyboard_state being "lpdikey->GetDeviceState(256, (LPVOID)keyboard_state);"

if userInput() == rightMovement
were userInput is the keystroke pressed and rightMovement is a pre-defined variable for what the keystroke must be to move in that direction
stevek2k
stevek2k
I think you are right though WM_KEYPRESS/KEYUP/KEYDOWN is the answer

when defining the keys i can use cin as it doesnt matter if it pauses, as it would be "Please enter a key" - wait for a reply - set key to this, but for the movement check it would need to be WM_* probably something like

if ( message = WM_KEYDOWN )
keyPress = WM_KEYDOWN;
if ( message = WM_KEYUP )
keyPress = null;

but what does WM_KEYDOWN pass, as far as i can see it's some sort of scan code but im not to sure how to convert that to ascii or basic hex, any ideas
jollyjeffers
jollyjeffers
Have you got your standard Win32 message pump up and running? They don't work through the standard input/output (std::cin and std::cout)...

You need the wParam and lParam values to go with the message to decode any specific details. Check this page out.

hth
Jack
<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ |
M2tM
M2tM
As a non-windows specific answer you can get SDL which handles keyboard input (and graphics and sound and networking and such... but you can just use the input stuff.)
_____"You're using a screwdriver to nail some glue to a ming vase. " -ToohrVyk
stevek2k
stevek2k
actually got it working, still needs some tweaking to allow 2 button control

int keyPressed;int keyPressed2;int player1_Up=87;int player1_Down=83;int player1_Left=65;int player1_Right=68;long CALLBACK WndProc( HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam ){	switch( uMessage )	{		case WM_CREATE: { return 0;	}		case WM_PAINT: { 			ValidateRect( hWnd, NULL );			return 0;		}		case WM_KEYDOWN: {			keyPressed = wParam;			if(keyPressed != wParam){				keyPressed2 = wParam;			}			return 0;		}				case WM_KEYUP: {			if(keyPressed==wParam){				keyReleased=wParam;				keyPressed = NULL;			}			if(keyPressed2==wParam){				keyReleased2=wParam;				keyPressed2 = NULL;			}			return 0;		}		case WM_CHAR: {			if(wParam>96 && wParam<123){				keyPressed = wParam - 32;				if(keyPressed != wParam){					keyPressed2 = wParam - 32;				}			} else {				keyPressed = wParam;				if(keyPressed != wParam){					keyPressed2 = wParam;				}			}			return 0;		}		case WM_DESTROY: {			PostQuitMessage( 0 );			return 0;		}		default: { return DefWindowProc( hWnd, uMessage, wParam, lParam ); }	}}/*direction function here*/bool PlayerMove(char direction[]) {	if (direction == "up") { if (keyPressed==player1_Up || keyPressed2==player1_Up) { return true; } else { return false; } }	else if (direction == "down") { if (keyPressed==player1_Down || keyPressed2==player1_Down) { return true; } else { return false; } }	else if (direction == "left") { if (keyPressed==player1_Left || keyPressed2==player1_Left) { return true; } else { return false; } }	else if (direction == "right") { if (keyPressed==player1_Right || keyPressed2==player1_Right) { return true; } else { return false; } }	else { return false; }}


I'm pretty damn pleased at getting that as i only started writing in c++ and directx 2-3 days ago

[Edited by - Muhammad Haggag on December 9, 2005 4:43:53 AM]
Drakex
Drakex
Muhammad's gonna be mad.. put that code in source tags. And if you don't know what that means, read the forum FAQ.

Well, besides your input code being rather.. erm, abstract.. an easier way to allow for customizable user input would be to use the method you were using before (that is, polling the keyboard with DirectInput), then loop through the keys array until you find one that's pressed. Then use that index as the customized key. You could do it like so:

int UpKey;...while(1){    // Process windows messages here    lpdikey->GetDeviceState(256, (LPVOID)keyboard_state);    for(int i = 0; i < 256; i++)        if(keyboard_state & 0x80)        {            UpKey = i;            break;        }    // Render your UI here}


I figured I might as well expand upon what I mean by your input code being abstract. I assume you're doing something like this:

if(PlayerMove("up"))    // move player upif(PlayerMove("down"))    // move player down


While it looks pretty, it's pretty foolish as well. You're doing a string compare for every single direction (and probably for every action). I take it you're doing it this way to add a level of indirection for the player input - that is, so you're not hard-coding the tests for keys pressed into the logic of moving the player, which is a good thing. However, it'd be much more efficient to use an enum to define the player's actions, like so:

enum{    PlayerMoveUp,    PlayerMoveDown,    PlayerMoveLeft,    PlayerMoveRight};...bool PlayerMove(int direction){    switch(direction)    {        case PlayerMoveUp:            if(keyboard_state[UpKey]) return true; else return false;        case PlayerMoveDown:            if(keyboard_state[DownKey]) return true; else return false;        // etc..    }}...if(PlayerMove(PlayerMoveUp))    // Move player upif(PlayerMove(PlayerMoveDown))    // Move player down
___________Hoo-rah.
Code-R
Code-R
keyPressed = wParam;if(keyPressed != wParam){   <...>}


how could that if statement EVER get a true condition??

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.