Ну, я пытаюсь избежать использования устаревшего DirectInput.
Но мне нужно, чтобы на каждом «кадре» или «итерации» игры хватало ВСЕ КЛЮЧЕВЫЕ СОСТОЯНИЯ, чтобы я мог действовать соответственно . Например, если игрок нажал на кнопку VK_RIGHT, он просто переместится на этот кадр прямо на пятно.
Проблема с сообщениями WM_INPUT заключается в том, что они могут появляться непредсказуемым числом раз за кадр из-за способа написания игрового цикла:
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() ;
}
}
Так что, если более одного сообщения WM_INPUT помещены туда, то все они будут обработаны перед Update () / Draw ().
Я решил эту проблему, используя массив BOOL, чтобы запомнить, какие клавиши были недоступны:
bool array_of_keys_that_are_down[ 256 ] ;
case WM_INPUT :
if( its keyboard input )
{
array_of_keys_that_are_down[ VK_CODE ] = TRUE ;
}
Это прекрасно работает, потому что функция Update () проверяет
void Update()
{
if( array_of_keys_that_are_down[ VK_RIGHT ] )
{
// Move the player right a bit
}
}
НО проблема в том, что сообщения WM_INPUT не генерируются часто достаточно . Между первым нажатием VK_RIGHT и последующими сообщениями VK_RIGHT существует задержка около 1 секунды, даже если игрок все время держал на нем палец. Это не похоже на DirectInput, где вы можете keyboard->GetDeviceState( 256, (void*)array_of_keys_that_are_down );
(выхватить все состояния клавиш в каждом кадре одним вызовом)
Так что я потерян. Кроме обращения к функциям GetAsyncKeystate () для каждой клавиши, которую мне нужно отслеживать, я не вижу способа избежать использования DirectInput, если вы не можете надежно выхватить все состояния клавиш в каждом кадре.
Мне кажется, что DirectInput был очень хорошим решением для этой проблемы, но если он устарел, то действительно должен быть какой-то способ сделать это удобно, используя только Win32 API.
В настоящее время array_of_keys_that_are_down
возвращается к каждому FALSE для каждого кадра.
memset( array_of_keys_that_are_down, 0, sizeof( array_of_keys_that_are_down ) ) ;
* EDIT
Я работал над этой проблемой, и одно из решений - сбросить состояние ключа только после его отпускания
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 ;
}
Мне не нравится это решение, потому что оно кажется хлипким . Если пользователь выключается из приложения, нажимая клавишу, эта клавиша будет «зависать» до тех пор, пока он не переключится назад и снова не нажмет ту же клавишу, потому что мы никогда не получим сообщение upstroke WM_INPUT . Это делает для странных ошибок "липкий ключ".