TheCherno / Sparky

Cross-Platform High Performance 2D/3D game engine for people like me who like to write code.
Apache License 2.0
1.1k stars 222 forks source link

Input handling should be mindful of a key's previous state #7

Closed Scipi closed 9 years ago

Scipi commented 9 years ago

The engine only shows us the current state of a key on a given frame. That is, on this frame is a key held or idle. This is limiting for cases where the previous state of a key also needs to be taken into account. For instance, for a semi automatic weapon in a game where the weapon shoots once every time you click the left mouse button you would need to have code like this to get it to work:

bool ready = true;
/*...*/
if(window.isMouseButtonPressed(GLFW_MOUSE_BUTTON_1)){
    if(ready){
        weapon.fire();
        ready = false;
    }
}else{
    ready = true;
}

We need a housekeeping bool to ensure our weapon fires on only the first frame a key is pressed. This is tedious to do for every case where we need this behavior and is prone to bugs. We should instead compare the previous and current states of each key/mouse button to see if a key has been pressed, held, released, or idle on the given frame and store that state for every key. So the code above turns into:

if(window.getMouseButtonState(GLFW_MOUSE_BUTTON_1) == BUTTON_PRESSED){
    weapon.fire();
}

Another case where we want something like an ability that powers up as a key is held and then activated when the key is released would go from this:

bool held = false;
/*...*/
if(window.isKeyPressed(GLFW_KEY_DOWN)){
    held = true;
    power.charge(dt);
}else if(held){
    power.activate();
    power.reset();
    held = false;
}

To this:

if(window.getKeyState(GLFW_KEY_DOWN) == KEY_HELD){
    power.charge(dt);
}else if(window.getKeyState(GLFW_KEY_DOWN) == KEY_RELEASED)){
    power.activate();
    power.reset();
}
arwassa commented 9 years ago

Wouldn't an event system be "better"? Where you can implement a KeyListener and attach it to a input handler. That way you could have a method fire every time a key is pressed, released and typed.

Scipi commented 9 years ago

An event system could work just as well. The only consideration is that every time your game state changes, you'll have to update the callback functions if you are changing what your inputs are doing. For instance, WASD might control the character ingame, but will control a selection bar in a menu or be disabled during a dialogue event. That's not difficult to do, however.

TheCherno commented 9 years ago

This has been fixed in Ep. 20. Thank you for opening an issue. :)