好吧,我试图避免使用已弃用的 DirectInput。
但是我需要在游戏的每个“帧”或“迭代”中抢夺所有关键状态,以便我可以采取相应的行动。例如,如果玩家按下 VK_RIGHT 键,那么他将在该帧上向右移动一点点。
WM_INPUT 消息的问题在于,由于游戏循环的编写方式,它们每帧会出现不可预测的次数:
味精消息; 而(一) { if( PeekMessage( &message, NULL, 0, 0, PM_REMOVE ) ) { 如果(message.message == WM_QUIT) { 休息 ; // 当 WM_QUIT 时保释 } TranslateMessage( &message ) ; DispatchMessage( &message ) ; } 别的 { // 没有消息,所以运行游戏。 更新() ; 画() ; } }
因此,如果在那里堆叠了多个WM_INPUT 消息,那么它们都将在 Update()/Draw() 之前得到处理。
我通过使用 BOOL 数组来记住哪些键已关闭,从而解决了这个问题:
bool array_of_keys_that_are_down[256]; 案例 WM_INPUT : if(它的键盘输入) { array_of_keys_that_are_down[VK_CODE] = TRUE; }
这很好用,因为 Update() 函数检查
无效更新() { 如果(array_of_keys_that_are_down[VK_RIGHT]) { // 将玩家向右移动一点 } }
但现在的问题是 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));
*编辑
我一直在解决这个问题,一个解决方案是只重置一个关键状态,一旦它被释放
案例 WM_INPUT : if(它的键盘输入) { 如果(它是按下) array_of_keys_that_are_down[VK_CODE] = TRUE; 别的 array_of_keys_that_are_down[VK_CODE] = FALSE; }
我不喜欢这个解决方案,因为它看起来很脆弱。如果用户在按下某个键时从应用程序中切换,那么该键将被“卡住”,直到他切换回来并再次按下相同的键,因为我们永远不会收到上行WM_INPUT消息。它会导致奇怪的“粘滞键”错误。