PC gamers in France and Belgium are used to the following routine:

  1. Start playing a brand new game.
  2. Strafe right and move backwards.
  3. Curse.
  4. Go to the options screen.
  5. Resume playing.

About every single game using the WASD control scheme (every FPS basically) forces us to remap the key assignments. A quick look at a closeup of my laptop keyboard will show you the root of the problem: an AZERTY keyboard has a few letters swapped compared to a QWERTY one.

The differences are not that big, only three letters are located differently (A, Z, M), but unfortunately two of these are right in the middle of the most standard keyboard control scheme of modern PC games.

Should you care? Honestly, probably not. As long as your game allows players to redefine their keys, us frog and snail eaters are usually (1) only a few tweaks away of enjoying the game. But that being said, correctly handling this problem in the default mapping is not that complicated either.

What the keyboard sends to the PC are key codes, which are “character agnostic”. They directly represent the physical positions of the keys. The standard way of assigning key codes originated with the IBM PC XT: the Scan Code Set 1. Further enhancements have been named Scan Code Set 2 and Scan Code Set 3.

Nowadays, most keyboards use Scan Code Set 2 to send the data to the computer, but the codes are translated back to Scan Code Set 1 when received (historically because of backward compatibility concerns). So everything dealing with scan codes on Windows can assume a Scan Code Set 1 numbering scheme.

Based on the scan code and the keyboard layout, Windows translates the key presses into Virtual Key codes. And this is where the physical positions are lost. You cannot assume that the key in the top left corner is labelled A, you have to go back to the scan codes.

The Scan Code Set 1 codes for the WASD keys are: 17, 30, 31, 32 (in that order). Notice how the values for ASD are consecutive. And to get the Virtual Key Codes most API require, you only have to call these functions:

forward = MapVirtualKey( 0x11, MAPVK_VSC_TO_VK );
  strafe_left = MapVirtualKey( 0x1E, MAPVK_VSC_TO_VK );
  backward = MapVirtualKey( 0x1F, MAPVK_VSC_TO_VK );
  strafe_right = MapVirtualKey( 0x20, MAPVK_VSC_TO_VK );

Only four lines of code to make millions of people happy, isn’t that great?

Don’t forget to check this article from Keith Judge about input handling for PC games here: /2011/04/25/input-for-modern-pc-games/

And here is some more complementary information:

  • http://msdn.microsoft.com/en-us/library/ms646306(v=vs.85).aspx
  • http://www.georgehernandez.com/h/xComputers/CharacterSets/ScanCodes.asp
  • http://www.win.tue.nl/~aeb/linux/kbd/scancodes-10.html
  • http://www.computer-engineering.org/ps2keyboard/
  • http://msdn.microsoft.com/en-us/goglobal/bb964651.aspx
  • http://seit.unsw.adfa.edu.au/staff/sites/hrp/personal/Sanskrit-External/Unicode-KbdsonWindows.pdf
  • http://babbage.cs.qc.edu/courses/cs345/Manuals/ms_scancode.pdf

(1) Not that long ago, right after starting a new game, I tried moving left but instead I inadvertently hit the shortcut for destroying the one and only item that could allow me to progress in the game. After remapping the keyboard I pointlessly walked around for 10 minutes, trying to figure out what I was supposed to do…