-1

I'm trying to make a simple python program that is meant to be run from a gnome-terminal.

I have an "@" character on screen that I want to move left (when left arrow pressed) and right (when right arrow pressed). How can I do this without using the curses library?

etuardu
  • 5,066
  • 3
  • 46
  • 58
tuatara
  • 21
  • 7
  • 1
    How are you doing the I/O in your program? And, why is this tagged _curses_, when you explicitly don't want to use Curses? And, why is this tagged _bash_, when it basically is a pure Python question? – user1934428 Jul 25 '22 at 06:05

1 Answers1

0

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.

etuardu
  • 5,066
  • 3
  • 46
  • 58