Sunday, February 14, 2010

Programmer - GetRawInputData vs GetAsyncKeyState()

Programmer Question

Well, I'm trying to avoid using the deprecated DirectInput.



But I need, at each "frame" or "iteration" of the game to snatch ALL KEY STATES so that I can act accordingly. For example, if the player is down on the VK_RIGHT key then he will move just a smidgen right on that frame.



The problem with WM_INPUT messages is they can appear an unpredictable number of times per frame, because of the way the game loop is written:




MSG message ;
while( 1 )
{
if( PeekMessage( &message, NULL, 0, 0, PM_REMOVE ) )
{
if( message.message == WM_QUIT )
{
break ; // bail when WM_QUIT
}

TranslateMessage( &message ) ;
DispatchMessage( &message ) ;
}
else
{
// No messages, so run the game.
Update() ;
Draw() ;
}
}



So if more than one WM_INPUT message is stacked there then they will all get processed before Update()/Draw().



I resolved this issue by using an array of BOOL to remember what keys were down:





bool array_of_keys_that_are_down[ 256 ] ;

case WM_INPUT :
if( its keyboard input )
{
array_of_keys_that_are_down[ VK_CODE ] = TRUE ;
}



That works fine because the Update() function checks





void Update()
{
if( array_of_keys_that_are_down[ VK_RIGHT ] )
{
// Move the player right a bit
}
}


BUT the problem is now that WM_INPUT messages don't get generated often enough. There's a delay of about 1 second between the first press of VK_RIGHT and subsequent VK_RIGHT messages, even if the player had his finger down on it the whole time. Its not like DirectInput where you can keyboard->GetDeviceState( 256, (void*)array_of_keys_that_are_down ); (snatch out all key states each frame with a single call)



So I'm lost. Other than resorting to GetAsyncKeystate() function calls for each key I need to monitor, I see no way to avoid using DirectInput if you can't snatch out all key states each frame reliably.



It seems to me that DirectInput was a very good solution to this problem, but if it was deprecated, then there really must be some way to do this conveniently using Win32 api only.



Currently array_of_keys_that_are_down gets reset back to all FALSE's every frame.




memset( array_of_keys_that_are_down, 0, sizeof( array_of_keys_that_are_down ) ) ;


*EDIT



I've been working on this problem and one solution is to only reset a key state, once its been released




case WM_INPUT :
if( its keyboard input )
{
if( its a down press )
array_of_keys_that_are_down[ VK_CODE ] = TRUE ;
else
array_of_keys_that_are_down[ VK_CODE ] = FALSE ;
}


I don't like this solution though because it seems flimsy. If the user switches away from the application while down on a key, then that key will be "stuck" until he switches back and presses that same key again because we'll never get the upstroke WM_INPUT message. It makes for weird "sticky key" bugs.

No comments:

Post a Comment

LinkWithin

Related Posts with Thumbnails