Reading keycodes instead of ASCII

From Sidvind
Jump to: navigation, search

This is an urgent request to all game developers! Please stop using the ASCII characters as input in games!


There is a good reason for this. The first and most important point is that people use different keyboard layouts. On a typical DVORAK keyboard "WASD" is spread across the keyboard. It's like using ",ALH" on a QWERTY keyboard. Second, even the QWERTY layout is different due to international keyboards.

Introducing keycodes[edit]

A keycode is a unique identifier that is associated a physical key. Not the meaning of the key, only the physical key. The keycode tells us nothing of it's meaning. In games this doesn't usually matter since we don't need what the OS thinks a key means, we assign meaning to the keys ourself. So instead of mapping "W" to "FORWARD" we map the corresponding keycode to "FORWARD".

Why can't the DVORAK users just change controls in the game?[edit]

Because it is annoying! It's not our fault you programmers are lazy. Also, say we don't feel like knowing the entire QWERTY layout in our head and be able to convert DVORAK to QWERTY to get the original controls.

My game requires text input[edit]

This is an interesting part. Just ask the OS to convert the keycode to ASCII. Actually, if you map action against ASCII you usually already do this whether you know it or not.


Code: Pseudocode

  1. case KEYDOWN:
  2.    keycode = event.key.keycode
  3.    action = actionMap[keycode]
  4.    ascii = KeycodeToASCII(keycode)
  6.    OnKeyDown(action, ascii)

This is my preferred method of reading input. When a key is pressed the keycode is read and mapped to an action and ASCII. Then they are passed to the input handler that figures out what to do with this. It is also worth to note that when converting a keycode you must also know which modifiers that affect that key right now. But as far as I know the system events raised upon a keypress contains enough information on all platforms.

Sample (XLib)[edit]

This sample is from production code. It does not map to an action but it sends the keycode and ASCII to the event manager. For a non-translatable character like ESC a NULL-terminator is returned.

Code: Xlib event loop

  1. while ( XPending(dpy) > 0 ){
  2.         XNextEvent(dpy, &event);
  3.         switch (event.type){
  4.                 /* Snip... */
  5.                 case KeyPress:
  6.                         char buf[2];
  7.                         int len;
  8.                         KeySym keysym_return;
  9.                         len = XLookupString(&event.xkey, buf, 1, &keysym_return, NULL);
  11.                         if ( len == 0 ){
  12.                                 buf[0] = '\0';
  13.                         }
  15.                         EventManager::singletonPtr()->dispatch(EventKeyboard::create(event.xkey.keycode,buf[0]));
  17.                         break;
  18.                 /* Snip... */
  19.         }