Skip to main content
1 of 2

What you can do is store boolean values for if the key was down or released and create some simple getters, a setter, and a "resetter" like so:

struct Key
{
    bool down;
    bool released;
};
bool KeyInput::IsKeyDown(uint32 keyCode)
{
    return s_keys[keyCode].down;
}

bool KeyInput::WasKeyReleased(uint32 keyCode)
{
    return s_keys[keyCode].released;
}

void KeyInput::SetKey(uint32 keyCode, bool isDown, bool isReleased)
{
    s_keys[keyCode].down = isDown;
    s_keys[keyCode].released = isReleased;
}

void KeyInput::ResetKeyReleased()
{
    for (int i = 0; i < NUM_KEYS; i++)
        s_keys[i].released = false;
}

Then in your WM_KEYDOWN and KEYUP handles:

case WM_KEYUP:
{
    bool wasDown = ((lParam & (1 << 30)) != 0);
    KeyInput::SetKey(wParam, false, wasDown);
}
break;
case WM_KEYDOWN:
{
    KeyInput::SetKey(wParam, true, false);
}
break;

And then finally before you handle the messages you call the reset function, and everything after your message handling would be your game loop, so something like:

        while (g_running)
        {
            KeyInput::ResetKeyReleased();

            MSG message;
            while (PeekMessage(&message, 0, 0, 0, PM_REMOVE))
            {
                if (message.message == WM_QUIT)
                    g_running = false;
                TranslateMessage(&message);
                DispatchMessageA(&message);
            }

            if (KeyInput::IsKeyDown('W'))
                OutputDebugStringA("W is down\n");
            if (KeyInput::WasKeyReleased(VK_SPACE))
                OutputDebugStringA("SPACE was just released\n");
        }

Hopefully this helped someone!