首页 > 解决方案 > 读取键盘状态 Win32 应用程序

问题描述

我正在使用 DirectX11 编写一个简单的 3D 游戏引擎,并且我正在使用 Win32 API 来读取用户输入(暂时,稍后我将切换到 DirectInput)。要读取键盘上按键的状态,我使用以下 API 函数:

void Game::ProcessInput()
{
    unsigned char keys[256];
    GetKeyboardState(keys);
    Input::GetInstance()->ProcessKeyboardInput(keys, mCamera, *mEntity, *mRenderer);
}

我在我的游戏循环中调用它并将键状态数组传递给我的输入类:

void Input::ProcessKeyboardInput(unsigned char *keys, Camera &camera, Entity &player, Renderer &renderer)
{
    static bool pressed = false;

    /* update camera position - translate camera */
    if (keys['A'] & 0x80)
        camera.MoveRight(-speed);
    if (keys['D'] & 0x80)
        camera.MoveRight(speed);
    if (keys['W'] & 0x80)
        camera.MoveForward(speed);
    if (keys['S'] & 0x80)
        camera.MoveForward(-speed);
    if (keys['Q'] & 0x80)
        camera.MoveUp(speed);
    if (keys['E'] & 0x80)
        camera.MoveUp(-speed);
    if (keys['P'] & 0x80)
        speed == SLOW ? speed = FAST : speed = SLOW;

    /* move player */
    if (keys[VK_LEFT] & 0x80)
        player.Rotate(-playerSpeed * 10.0);
    if (keys[VK_RIGHT] & 0x80)
        player.Rotate(playerSpeed * 10.0);
    if (keys[VK_UP] & 0x80)
        player.MoveForward(playerSpeed);
    if (keys[VK_DOWN] & 0x80)
        player.MoveForward(-playerSpeed);
    if (keys[VK_SPACE] & 0x80)
        player.Jump();

    /* control rendering */
    if (keys['O'] & 0x80 && !pressed)
    {
        renderer.TogglePostProcessing();
        pressed = true;
    }
    else
        pressed = false;

}

我认为我可以通过检查最高位(0x80 位掩码)来检测键是否被按住,这适用于移动键,但我希望“O”键在我按下它并重新切换时切换我的渲染器-当我释放它后再次按下它时切换它,但代码不断检测到键。我究竟做错了什么?

标签: winapiinputkeyboard

解决方案


您需要将!pressed支票移动到if块内,而不是if本身:

if (keys['O'] & 0x80) {
    if (!pressed) {
        renderer.TogglePostProcessing();
        pressed = true;
    }
}
else
    pressed = false;

在您的原始代码中:

if (keys['O'] & 0x80 && !pressed)
{
    renderer.TogglePostProcessing();
    pressed = true;
}
else
    pressed = false;

'O'按住 时,您会不断地来回切换,pressed从而切换渲染器:

Pass #1: pressed==false, so (keys['O'] & 0x80 && !pressed) == true,所以渲染器被切换并pressed设置为 true。

Pass #2: pressed==true, so (keys['O'] & 0x80 && !pressed) == false, sopressed设置为 false。

Pass #3: pressed==false, so (keys['O'] & 0x80 && !pressed) == true,所以渲染器被切换并pressed设置为 true。

依此类推,直到你最终释放'O'......

在新代码中,pressed仅当keys['O'] & 0x80第一次评估为 true 时才设置为 true,并保持设置为 true 直到keys['O'] & 0x80评估为 false。keys['O'] & 0x80然后在再次评估为真时切换一次。等等...


推荐阅读