Keyboards Are Evil
OK - so I hear you asking, what could possibly be evil about keyboards (apart from the stoopid CapsLock key of course!).
Contents
A Practical Demonstration.
Try this (Yes - NOW! - I'll wait while you do it...):
- Open a text entry window of some kind.
- Press down (and hold down) the 'E' key.
- Without letting go, press down (and hold down) the 'C' key.
- Now tap repeatedly on the 'U' key. Do you see any u's coming out on the screen? No? I didn't think so.
- If you have an older keyboard, maybe you did see a 'u' - but you probably see some m's too?!?
- Try typing some other characters - notice that some work but some are either blocked or generate 'ghost' characters.
- Try holding down other pairs of keys and tapping on a third - for almost any pair you choose, there are several other keys that don't work.
Clearly this is a bad thing for programs that expect the user to hold down keys to make things happen. Games with two players using the keyboard at once are particularly vulnerable to this.
So What's going on?
For a detailed explanation, read this article - but if all you need to know is the simple explanation, read on.
Well, I've researched and experimented and discovered the answer.
- The keyboard is internally arranged into rows and columns with a key at each intersection. The number of rows and columns and which keys are where *seems* to be the same for all 'normal' keys on every keyboard I've tried - but it seems that you can't really rely on that - especially on non-PC keyboards.
- When you press any two keys, each activates one row wire and one column wire and they can be recognised uniquely. However, when you hit a third key, one of two things can happen:
- It can activate either a different row or a different column than either of the other two keys that are held down - and it will be recognised.
- It can activate the same row as one of the two keys and the same column as the other...this is "A Bad Thing".
- What happens in case (2) depends on how old your keyboard is.
- On older keyboards with less sophisticated controllers and a diode at each row column intersection, you can get a 'ghost' key hit - which is the key that is at the row and column that the third key didn't hit but the first two keys did hit. Hence if your first keystroke hit ROW 3 COLUMN 4, and your second keystroke hit ROW 5 COLUMN 6, then if your third keystroke hit ROW 3 COLUMN 6 then the ghost keystroke will be whatever key happens to be at ROW 5 COLUMN 4.
- With newer keyboards, this condition is detected in the keyboard controller and neither the third key you hit nor the ghost key will be sent off to the PC.
On all of the keyboards I've tried (four of them so far), all but my ancient Compaq laptop work the second way and all of them have the rows and columns organised approximately according to the rows and columns of keys on the physical keyboard...but only approximately. I'd expect holding down 'E' and 'C' to lock out 'Y' and 'N' - but it doesn't.
So, whenever you have two keys held down and the third one lies at a location that would form an 'L' shape in the keyboard matrix (eg you press 'E' and 'M' - and then try to press either 'C' or 'U') - then the third keystroke will be ignored on a modern keyboard or you'll get a ghost keystroke on an older one (so in that example, if you hit 'C' at the third key, the 'U' will also appear to have been typed even though your fingers never came near it.)
How to handle this
In a two player game for example, you'll have to be careful NOT to assign the keys in such a way that the actions of one player can block the keys of the other.
I first discovered this effect when I gave one player 'W','A','S' and 'Z' (which is a 'diamond' pattern on a QWERTY keyboard) and the other player 'I','J','K' and 'M' (another diamond pattern) as the means to move their characters around on the screen. When the lefthand player presses 'W' and 'S' to travel North-East, the other player will find that moving North, East or West by pressing 'I','J' or 'K' won't work anymore.
We have to be very careful to allocate keys that don't interfere with one another.
For example, I could give one player 'Q','W','E','R','T' to play with. That would mean that I would EITHER have to give the other player 'Y', 'U', 'I', 'O' and 'P' (same keyboard ROW but different COLUMNS) or give him 'H', 'J', 'K', 'L' and ';' (different row and different Columns).
Of course this isn't going to be portable to people with AZERTY keyboards or people who have re-mapped to Dvorjak layouts - but so long as you explain the problem to your users and provide a way to re-map the keys, you'll be OK.
The Keyboard Matrix
The arrangement of keys into rows and columns may differ between PC keyboards, but for the four types that I tested, they all agreed with this layout:
E | F3 | D | F4 | C | ??? | F2 | 3 |
W | CapsLock | S | ??? | X | ??? | F1 | 2 |
Q | Tab | A | Esc | Z | ??? | ~ | 1 |
Pause | ??? | ??? | ??? | RightCtrl | ??? | LeftCtrl | F5 |
R | T | F | G | V | B | 5 | 4 |
U | Y | J | H | M | N | 6 | 7 |
I | ] | K | F6 | , | ??? | = | 8 |
O | F7 | L | ??? | . | Menu | F8 | 9 |
P | [ | ; | ' | ??? | / | - | 0 |
ScrollLock | ??? | ??? | LeftAlt | ??? | RightAlt | ??? | SysRq |
??? | Backspace | \ | F11 | Enter | F12 | F9 | F10 |
Keypad 7 | Keypad 4 | Keypad 1 | Space | NumLock | DownArrow | Delete | ??? |
Keypad 8 | Keypad 5 | Keypad 2 | Keypad 0 | Keypad / | RightArrow | Insert | ??? |
Keypad 9 | Keypad 6 | Keypad 3 | Keypad . | Keypad * | Keypad - | PgUp | PgDown |
Keypad + | ??? | KeypadEnter | UpArrow | ??? | LeftArrow | Home | End |
??? | LeftShift | RightShift | ??? | ??? | ??? | ??? | ??? |
??? | LeftMeta | ??? | ??? | ??? | ??? | ??? | ??? |
??? | ??? | RightMeta | ??? | ??? | ??? | ??? | ??? |
Conclusion
We have to be careful in picking key assignments because KEYBOARDS ARE EVIL.