Ty Staszak
Ty Staszak

Reputation: 115

unicode for arrow keys?

I am trying to make a game where you can instantly have the user's input be transmitted to the computer instead of having to press enter every time. I know how to do that, but I cannot seem to find the unicode number for the arrow keys. Is there unicode for that, or am I just going to be stuck with wasd?

class _GetchUnix:
    def __init__(self):
        import tty, sys
    def __call__(self):
        import sys, tty, termios
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch
class _GetchWindows:
    def __init__(self):
        import msvcrt
    def __call__(self):
        import msvcrt
        return msvcrt.getch()
class _Getch:
    def __init__(self):
        try:
            self.impl = _GetchWindows()
        except ImportError:
            self.impl = _GetchUnix()
    def __call__(self): return self.impl()
getch = Getch()

I using getch.impl() as a trial-or-error input, as in if there's a key being pressed when the function is called, it returns that key, and moves on. If there's no key being pressed, it just moves on.
I'm using Python 2.7.10

Upvotes: 1

Views: 4795

Answers (1)

Terry Jan Reedy
Terry Jan Reedy

Reputation: 19144

Start by reading the relevant doc for msvcrt.

msvcrt.kbhit()

Return true if a keypress is waiting to be read.

msvcrt.getch()

Read a keypress and return the resulting character as a byte string. Nothing is echoed to the console. This call will block if a keypress is not already available, but will not wait for Enter to be pressed. If the pressed key was a special function key, this will return '\000' or '\xe0'; the next call will return the keycode. The Control-C keypress cannot be read with this function.

Notice that getch blocks and requires two calls for special function keys, which include arrow keys (they initially return b'\xe0).

Then use sys.platform and write two versions of a get_arrow function.

import sys
if sys.platform == 'win32':
    import msvcrt as ms
    d = {b'H': 'up', b'K': 'lt', b'P': 'dn', b'M': 'rt'}
    def get_arrow():
        if ms.kbhit() and ms.getch() == b'\xe0':
            return d.get(ms.getch(), None)
        else:
            return None
else:  # unix
...

I experimentally determined the mapping of keys to codes with the following code. ( This will not work when run in IDLE and maybe not in other GUI frameworks, as getch conflicts with GUI handling of the keyboard.)

>>> import msvcrt as ms
>>> for i in range(8): print(ms.getch())
...
b'\xe0'
b'H'
b'\xe0'
b'K'
b'\xe0'
b'P'
b'\xe0'
b'M'

I tested the function on Windows with

while True:
    dir = get_arrow()
    if dir: print(dir)

Upvotes: 1

Related Questions