KalyanChakravarthy.net

home photos apps about

Detecting multiple arrow key strokes

Sun 06 November 2011

Most games or applications which make use of arrow keys, sometimes require the use of multiple combinations like UP+RIGHT, LEFT+DOWN, etc also. I was trying to do the same for a 3d game I was trying to write in Processing. It might seem like a simple problem, which it is, surprisingly i couldn't find anything on it. So after playing around with a little bit i figured it out.

Each key when pressed and released individually triggers a separate event, including for combinations of keys. Hence the way to test if both Up+Right keys are pressed, is to store the pressed status of individual keys, and clear their status individually when each key is released.

Here is the processing code. The logic should be applicable for any language and platform.

<code lang="processing">
class KeyStateReader {
  //binary sequence for easy state storage
  static final int K_UP = 1;
  static final int K_RIGHT = 2;
  static final int K_DOWN = 4;
  static final int K_LEFT = 8;
  int keyState;
  //combine the key stats into single variable by logical |
  public void onKeyPress() {
    int kType = getK();
    keyState |= kType;
  }
  //on release clear individual bits
  public void onKeyRelease() {
    int kType = getK();
    keyState = keyState ^ kType;
  }
  // pass a key combo using logical or '|' ( UP | RIGHT ) to see if it exists.
  public boolean isKey(int k) {
    return (k & keyState) != 0 ? true : false;
  }
  // do we have any at all ?
  public boolean hasAnyKey() {
    return keyState > 0;
  }
  public int getK() {
    switch(keyCode) {
      case UP: return K_UP;
      case DOWN: return K_DOWN;
      case LEFT: return K_LEFT;
      case RIGHT: return K_RIGHT;
    }
    return -1;
  }
}
KeyStateReader keyState = new KeyStateReader();
void keyPressed() {
  keyState.onKeyPress();
}
void keyReleased() {
  keyState.onKeyRelease();
}
To check for key combos you can now do this
<code lang="processing">void checkKeyCombo() {
  // for UP+RIGHT
  if( keyState.isKey( KeyStateReader.K_UP | KeyStateReader.K_RIGHT ) ) {
    do_something_up_right();
  }
  // You can even check them individually
  if( keyState.isKey( KeyStateReader.K_UP ) ) {
    do_something_up();
  }
  if( keyState.isKey( KeyStateReader.K_RIGHT ) ) {
    do_something_right();
  }
}

There are definitely other ways to do it too, like maintain an array with all the keyCodes and check if the key being tested is available in the array. That way you will be able to track multiple keys and you wouldn't have to re-define key codes for each of them.