I'd like to move the camera in the game world using the W-A-S-D keys. I always used the GetAsyncKeyState to accomplish this, however I'd like to try and rely solely on windows messages this time. The problem is that key repeat rate has an initial delay so there is a pause between pressing the move key and the camera actually moving. I've read a few threads on this subject and people recommend using a custom timing function to implement this, which I did, however there is something wrong with way I have it at the moment. This is some relevant code:
case WM_KEYDOWN:
{
//mKeyDownMap is declared as std::map<int, bool> , it just matches the keycode of the key to its down state, false key is up, true - down
if (wParam == 0x57) //W key
if (!mKeyDownMap[0x57])
{
SetTimer(mWindow, W_TIMER, 400, NULL);
mKeyDownMap[0x57] = true;
}
if (wParam == 0x53) //S key
if (!mKeyDownMap[0x53])
{
SetTimer(mWindow, S_TIMER, 400, NULL);
mKeyDownMap[0x53] = true;
}
//... same for other keys
}break;
case WM_TIMER:
{
if (wParam == W_TIMER)
mCamera.Move(XMFLOAT3(0.0f, 0.0f, 1.0f));
else if(wParam == S_TIMER)
mCamera.Move(XMFLOAT3(0.0f, 0.0f, -1.0f));
//..same for other 2 keys
} break;
case WM_KEYUP:
{
if (wParam == 0x57) //W key
{
KillTimer(mWindow, W_TIMER);
mKeyDownMap[0x57] = false;
}
if (wParam == 0x53) //S key
{
KillTimer(mWindow, S_TIMER);
mKeyDownMap[0x53] = false;
}
//... same goes for other 2 keys
}break;
The exact issue with this code is when I press the W key once and let go fast, the WM_TIMER is never received, however if I hold the key down then it comes in. I suspect that its got something to do with the processing order of the messages, where WM_KEYDOWN is prossessed and WM_KEYUP is processed right after, killing the timer that never giving the timer a chance to send the WM_TIMER message. I can start writing some annoying workarounds, maybe making sure the mCamera.Move is executed at least once, however I feel like there should be a better way to handle this. I'm not even sure that using these timers is the way it should be done. Can anyone suggest something?
Edit: After reading the SetTimer doc, I realized that by calling it again before the first instance of it is killed resets it, so I added a map that holds the previous state saved.
Edit 2: Well, I got it running a bit smoother by lower the timer interval to 10ms. However I'd still like to get some feedback if I'm doing this whole thing right.