c++ - GetRawInputData 与 GetAsyncKeyState()

标签 c++ winapi directx directinput

好吧,我正在努力避免使用已弃用的 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 ) ) ;

*编辑

我一直在研究这个问题,一个解决方案是只重置一个关键状态,一旦它被释放

    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 ;
        }

不过我不喜欢这个解决方案,因为它看起来不可靠。如果用户在按下某个键时离开应用程序,那么该键将“卡住”,直到他切换回来并再次按下同一个键,因为我们永远不会收到上击 WM_INPUT 消息。它会产生奇怪的“粘滞键”错误。

最佳答案

您可以使用 GetKeyboardState反而。你通常想要的是两个数组;一个存储前一帧的输入状态,一个存储当前帧。这允许诸如区分被持有和被触发之类的事情。

// note, cannot use bool because of specialization
std::vector<unsigned char> previous(256);
std::vector<unsigned char> current(256);

// in update_keys or similar:
current.swap(previous); // constant time, yay
GetKeyboardState(&current[0]); // normally do error checking

大功告成。

关于c++ - GetRawInputData 与 GetAsyncKeyState(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2261847/

相关文章:

c++ - 在非VS项目中包含VS DLL

c - 串行端口 : Read data problem with loopback, 未读取任何内容

c - 为什么 Mingw32 提供的 WinBase.h 不包括 Windows 7 的 `SetProcessDEPPolicy'?

c++ - 在天穹上使用点光源的奇怪照明效果

c++ - ASSIMP 网格与 directx9

c++ - "there is no smaller array object that satisfies these constraints"是什么意思?

c++ - 如何使一个部分特化模板类成为另一个部分特化模板类的 friend ?

C++ 运算符重载,operator bool() 和 operator !()

c++ - HttpFilterProc 在 C++ 中不起作用

algorithm - 渲染不透明、启用 Alpha 和启用混合的对象