1

I'm creating a game that is supposed to run on the command line. The game uses text as a the canvas ( the software prints text in a shape of a rectangle, and when the text changes, the image changes). I've created a little scrip to test how this would work

import os

# function for printing out the game display grid
def printgrid(input):
    for i in range(len(input)):
        for j in range(len(input[0]):
            print(input[i][j], end='')
        print('') # newline after each row

grid = [['#' for x in range(10)] for x in range(10)]
while (True):
    # refresh the screen and reprint
    os.system('clear')
    printgrid(grid)

Unfortunately the code seems to be printing the grid too slowly resulting in a noticable scrolling effect during the printing, which would make the game unplayable.

  1. Is there a faster way to print text in python?

  2. Could the cause of this scrolling effect just be the fact that I have not made any framerate cap on this code, and it just happens to show the current output when the computer monitor refreshes?

  3. If my approach is completely wrong, what would be the best way to do this?
user3391899
  • 95
  • 1
  • 5

3 Answers3

3

Printing to the console is usually slow, since most languages tend to wait until the message is displayed before moving on. There are ways around thid with your current approach.

If you use the file API, via sys.stdout, you can write() as many times as you want and call flush() when the screen is ready to be printed. You may also try calling write() as little as possible, perhaps building strings in memory and outputting them whole.

The frame-rate cap is definitely needed, though. The console is not a fast interface, it can't do high frame-rates. Implement a cap, and play with the number.

In short:

  • Call write() as little as possible
  • Call flush() only when you're ready to render
  • Cap the frame-rate at 10, then 20, then 30. Experiment

The other approach, which will definitely bring your game up to speed, is to use ncurses. With it, you can update only the portions of the screen that need re-rendering, instead of reprinting the screen whole.

salezica
  • 74,081
  • 25
  • 105
  • 166
1

Since Python 3.3 print() supports the keyword argument "flush" (see documentation):

print('Hello World!', flush=True)
Sait
  • 19,045
  • 18
  • 72
  • 99
1

Assuming you're using a Unix-like OS (Linux or Mac) then the best way to do this would be using curses ( https://docs.python.org/3/howto/curses.html ). However, this can be a lot of effort and would probably be overkill for what you're doing.

If you choose to go the simple route, then you should put a delay in your repainting. Right now you're clearing immediately after finishing putting everything on the screen, which is giving you problems. Instead, you can do something like this:

from time import sleep
while (True):
    # refresh the screen and reprint
    os.system('clear')
    printgrid(grid)

    sleep(0.1)    # sleep 0.1 seconds before clear

What this will do is leave the text on the screen for longer before repainting which will make it easier to see. Play with the amount of time you sleep and find what looks best for your application.

Daniel Centore
  • 3,220
  • 1
  • 18
  • 39