You will have a hard time doing that without using a library such us curses
, and I discourage you to do so since you would have to deal with several pitfalls.
That said, you are facing two issues: detecting key presses and printing over the same line several times.
If you do some research you would find that in linux you can read from the standard input disabling the buffering using tty
and termios
(see here for example). You may use that to detect the pressing of an arrow key.
About printing on the same line, you have some special control character such as the carriage return \r
which you may use to achieve your goal.
Putting everything together, the most basic program to move a "@" using the arrow keys would look like this:
#!/usr/bin/env python3
import sys
import termios
import tty
K_RIGHT = b'\x1b[C'
K_LEFT = b'\x1b[D'
def read_keys():
stdin = sys.stdin.fileno()
tattr = termios.tcgetattr(stdin)
try:
tty.setcbreak(stdin, termios.TCSANOW)
while True:
yield sys.stdin.buffer.read1()
except KeyboardInterrupt:
yield None
finally:
termios.tcsetattr(stdin, termios.TCSANOW, tattr)
def reset_line():
print(
'\033[F' + # move up
'\033[K', # clear row
end=''
)
def print_sprite(x):
print((' '*x) + '@')
if __name__ == '__main__':
print('Press Ctrl+c to quit')
sprite_x = 0
print_sprite(sprite_x)
for k in read_keys():
if k == K_LEFT:
sprite_x -= 1
if k == K_RIGHT:
sprite_x += 1
reset_line()
print_sprite(sprite_x)
As you can see this is far away from being a "simple program" and the curses
library is definitely the way to go.