Agent Biscutt
Agent Biscutt

Reputation: 737

Hide non-standard python user input

I am creating a console game, which takes user key presses.

I had trouble with hiding the letters that then spread across the screen simply because the user is pressing a button.

It won't work with modules like getpass, and I have already tried various ANSI codes to attempt to hide the text. The background is also full of text characters and symbols, so that stops just a complete ANSI character disappearo. I also don't wanna have to call os.system("clear") every frame, because even calling it once every second bugs out the terminal.

What I want to know, is whether there is a way to catch key presses without having said key appear on the console

Here is the board class I am using, and the draw() method inside is how I have been drawing it to the terminal:

class board:
  def __init__(self,length):
    import random
    self.random=random
    self.characters=[" ","░","▒","▓","█"]
    self.length=length
    self.dithering=False
    self.board=[[self.random.choice(self.characters) for y in range(self.length)] for x in range(self.length)]
  def draw(self,colour=None):
    if colour==None:
      colour=RGB(0,1,0)
    for x in range(len(self.board)):
      for y in range(len(self.board)):
        if self.board[y][x]==None:
          continue
        f=1
        if self.dithering==True:
          f=self.random.random()+0.5 # faintness
        print(f"\u001b[{y};{x*2+1}H\x1b[38;2;{int(colour.r*f)};{int(colour.g*f)};{int(colour.b*f)}m{str(self.board[y][x])*2}",end="")
    print("\x1b[0m")
  def redecorate(self,characters=None):
    if characters==None:
      characters=self.characters
    self.board=[[self.random.choice(characters) for y in range(self.length)] for x in range(self.length)]
  def empty(self):
    self.board=[[None for y in range(self.length)] for x in range(self.length)]

class RGB:
  def __init__(self,r,g,b):
    self.r=r*255
    self.g=g*255
    self.b=b*255

Upvotes: 1

Views: 262

Answers (1)

USLTD
USLTD

Reputation: 309

To catch key presses without displaying them you need getch function. On Windows you can use msvcrt module to capture it, while on Unix-like and Linux platforms you need to implement it by yourself, although it is easy.

Here is code for Windows:

from msvcrt import getch

And for Linux and Unix-like platforms:

import sys
import termios
import tty
def getch() -> str:
    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

NOTE: some keys are more than one char long (like arrow keys which are 3 char long) so you will need to run getch few times to fully capture it.

Upvotes: 1

Related Questions