Reputation: 1766
I'm coding a simple 3D game engine with DirectX11 and I'm using Win32 API to read user input (for the time being, later I'll switch to DirectInput). To read the state of keys on the keyboard I use the following API function:
void Game::ProcessInput()
{
unsigned char keys[256];
GetKeyboardState(keys);
Input::GetInstance()->ProcessKeyboardInput(keys, mCamera, *mEntity, *mRenderer);
}
I call it in my game loop and pass the array of key states to my Input class:
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;
}
I thought that I can detect if a key is hold down by checking the topmost bit (0x80 bit mask), and this works for the movement keys, but I want the 'O' key to toggle my renderer when I press it and re-toggle it when I press it again after releasing it, but the code continuously detect the key. What am I doing wrong?
Upvotes: 0
Views: 414
Reputation: 596287
You need to move your !pressed
check inside of the if
block, rather than in the if
itself:
if (keys['O'] & 0x80) {
if (!pressed) {
renderer.TogglePostProcessing();
pressed = true;
}
}
else
pressed = false;
In your original code:
if (keys['O'] & 0x80 && !pressed)
{
renderer.TogglePostProcessing();
pressed = true;
}
else
pressed = false;
While 'O'
is held down, you are continuously toggling pressed
back and forth, and thus toggling the renderer:
Pass #1: pressed==false
, so (keys['O'] & 0x80 && !pressed) == true
, so the renderer is toggled and pressed
is set to true.
Pass #2: pressed==true
, so (keys['O'] & 0x80 && !pressed) == false
, so pressed
is set to false.
Pass #3: pressed==false
, so (keys['O'] & 0x80 && !pressed) == true
, so the renderer is toggled and pressed
is set to true.
And so on, until you eventually release 'O'
...
In the new code, pressed
is set to true only when keys['O'] & 0x80
evaluates as true for the first time, and remains set as true until keys['O'] & 0x80
evaluates as false. Then toggles one time when keys['O'] & 0x80
evaluates as true again. And so on...
Upvotes: 1