Detecting key presses

T

tylertacky

Ok, I'm pretty new to python, so this might be a stupid question. I'm
trying to write a simple text-based pong clone, and I can't figure out
how to read key presses to move the paddles. I just need something that
does the same thing as getch() and kbhit(). I can't use those because
their windows only, and I'm running Linux.

Someone suggested using curses, but that does crazy things with my
output, and leaves the terminal unusable after the program closes.
 
F

Fan Zhang

Ok, I'm pretty new to python, so this might be a stupid question. I'm
trying to write a simple text-based pong clone, and I can't figure out
how to read key presses to move the paddles. I just need something that
does the same thing as getch() and kbhit(). I can't use those because
their windows only, and I'm running Linux.

Someone suggested using curses, but that does crazy things with my
output, and leaves the terminal unusable after the program closes.

The python.org site has a faq about getting keystroke.
It uses termios and fcntl modules.
Here's the link:
http://www.python.org/doc/faq/library/#how-do-i-get-a-single-keypress-at-a-time

Hope it can help you!
 
D

Diez B. Roggisch

Ok, I'm pretty new to python, so this might be a stupid question. I'm
trying to write a simple text-based pong clone, and I can't figure out
how to read key presses to move the paddles. I just need something that
does the same thing as getch() and kbhit(). I can't use those because
their windows only, and I'm running Linux.

Someone suggested using curses, but that does crazy things with my
output, and leaves the terminal unusable after the program closes.

Maybe using pygame for a graphical version is appealing to you -
additionally, the event-sytem of it will do what you ask for.

Diez
 
P

peter

Not a stupid question at all - its something I was looking for, and was
(and still am) surprised not to find a cross platform implementation.
It must be possible - for a short while I dabbled with yabasic and
there the same source code would recognise a keypress in both Windows
and Linux.

My solution was:-

# Await key and return code - dos only
def _keycode_msvcrt(self):
#Loop till key pressed
while 1:
if msvcrt.kbhit():
k=ord(msvcrt.getch())
if k==0 or k==224: #Special keys
k=1000+ord(msvcrt.getch()) #return 1000+ 2nd code
pass
break
pass
pass
return k

# Await key and return code - linux only
def _keycode_linux2(self):
# Loop till key pressed
# Set up keycode list
a=[0,0,0,0,0,0]

# Press a key and populate list
try:
os.system('stty -icanon')
os.system('stty -echo')
a[0]=ord(sys.stdin.read(1))
if a[0]==27:
a[1]=ord(sys.stdin.read(1))
if a[1]==91:
a[2]=ord(sys.stdin.read(1))
if (a[2]>=49 and a[2]<=54) or a[2]==91:
a[3]=ord(sys.stdin.read(1))
if a[3]>=48 and a[3]<=57:
a[4]=ord(sys.stdin.read(1))
finally:
os.system('stty echo')
os.system('stty icanon')

# Decode keypress
if a==[ 10, 0, 0, 0, 0, 0]: k= 13 # Enter
elif a==[ 27, 27, 0, 0, 0, 0]: k= 27 # Esc (double
press)
elif a==[ 27, 91, 91, 65, 0, 0]: k=1059 # F1
elif a==[ 27, 91, 91, 66, 0, 0]: k=1060 # F2
elif a==[ 27, 91, 91, 67, 0, 0]: k=1061 # F3
elif a==[ 27, 91, 91, 68, 0, 0]: k=1062 # F4
elif a==[ 27, 91, 91, 69, 0, 0]: k=1063 # F5
elif a==[ 27, 91, 49, 55, 126, 0]: k=1064 # F6
elif a==[ 27, 91, 49, 56, 126, 0]: k=1065 # F7
elif a==[ 27, 91, 49, 57, 126, 0]: k=1066 # F8
elif a==[ 27, 91, 50, 48, 126, 0]: k=1067 # F9
elif a==[ 27, 91, 50, 49, 126, 0]: k=1068 # F10
elif a==[ 27, 91, 50, 51, 126, 0]: k=1133 # F11
elif a==[ 27, 91, 50, 52, 126, 0]: k=1134 # F12
elif a==[ 27, 91, 50, 126, 0, 0]: k=1082 # Ins
elif a==[ 27, 91, 51, 126, 0, 0]: k=1083 # Del
elif a==[ 27, 91, 49, 126, 0, 0]: k=1071 # Home
elif a==[ 27, 91, 52, 126, 0, 0]: k=1079 # End
elif a==[ 27, 91, 53, 126, 0, 0]: k=1073 # Pg Up
elif a==[ 27, 91, 54, 126, 0, 0]: k=1081 # Pg Dn
elif a==[ 27, 91, 65, 0, 0, 0]: k=1072 # Up
elif a==[ 27, 91, 66, 0, 0, 0]: k=1080 # Down
elif a==[ 27, 91, 68, 0, 0, 0]: k=1075 # Left
elif a==[ 27, 91, 67, 0, 0, 0]: k=1077 # Right
elif a==[127, 0, 0, 0, 0, 0]: k= 8 # Backspace
else: k=a[0] # Ascii code

# Done
return k


# Return key code
def key(self,case='NONE'):

# Get OS name and call platform specific function
a=sys.platform
if a=='linux2': #Linux (works on Fedora
Core 1 and 3)
k=self._keycode_linux2()
elif a=='win32': #windows
k=self._keycode_msvcrt()
else: #unknown
k=ord(raw_input())

# Adjust case
if case=='UPPER':
if k>=97 and k<=122:
k=k-32
if case=='LOWER':
if k>=65 and k<=90:
k=k+32

# Done
return k

A bit clumsy, I know (for example it needs a a double press to
recognise the escape key), and I'm not sure I understand why it works,
but for me it was a passable solution.

Peter
 
B

blue99

Someone suggested using curses, but that does crazy things with my
output, and leaves the terminal unusable after the program closes.

It's very good suggestion but you should use also initscr
and endwin functions.

Regards,
Rob
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,141
Latest member
BlissKeto
Top