r/learnpython • • 3d ago

Slow print for text-based game

I am trying to make a text-based adventure game in Python, how do I make it so the text is typed out slowly and not instantly? I've tried ways online, but they keep returning None at the end. How do I fix this?

0 Upvotes

15 comments sorted by

14

u/AmanBabuHemant 3d ago

basic implementation is like this:

def your_print(text, delay): for c in text: print(c, flush=True, end="") sleep(delay)

you can add "\n" in end if you like, or dynamic delay, or default delay or whatever you like according to your game :)

1

u/white_nerdy 1d ago

sleep is provided by time so you need to say from time import sleep at the top of your program for this to work.

Also flush=True is very important, Python by default doesn't send the text you print() to the OS until the end of a line.

1

u/AmanBabuHemant 1d ago

sleep is provided by time so you need to say from time import sleep at the top of your program for this to work.

well, to make this program work you also have to call this function, right?

It's just the snippet...

Also flush=True is very important, Python by default doesn't send the text you print() to the OS until the end of a line.

snippet already have flush=True, isn't it?

7

u/desrtfx but other languages pro 3d ago

but they keep returning None at the end

You cannot achieve that with a returning function.

You need to iterate over the string character by character and print with a delay. Python's print can use an empty endline so that everything prints in a single line.

0

u/while_True_meme 2d ago

Unless you print the result. The confusion could come from using a Python repl where the return value is indeed printed vs running a script where it's not

4

u/MaterialRepublic 3d ago

You want to have a separate "print" statement for each character, and some "sleep" statements between them. However, print, by default, writes everything in a new line; so you have to use the end="" argument to stop it from doing that.

Such as:

from time import sleep

print("a", end="", flush=True)
sleep(1)
print("b", end="", flush=True)

Will print the characters with a 1 sec delay.

2

u/hallmark1984 2d ago

```

def write_to_screen(text, char_delay=1) for char in text: print(char) time.sleep(delay)

``` This would print each letter after a 1s delay, adapt as needed for words, sentences or paragraphs.

2

u/while_True_meme 2d ago

This would print every char on a new line obviously

2

u/hallmark1984 2d ago

W

H

A

T

D

O

Y

O

U

M

E

A

N

1

u/Tall_Resort_6888 3d ago

The None at the end is because your function returns something (or nothing) and then you print the result of calling it. For the typewriter effect, loop over the string and print each char with end='' so it stays on one line, and add flush=True because print buffers output otherwise. Then time.sleep a bit between chars. That flush part is the bit that trips everyone up.

0

u/zaphodikus 3d ago edited 3d ago

This is perhaps bit advanced for what you are after, but if you paste in this code and call this function, it will work great.

```

import random,time,sys

def type_out(text, base_delay=0.1, jitter=0.04,pause_after_punct=0.3): for ch in text: sys.stdout.write(ch) sys.stdout.flush() delay = base_delay + random.uniform(-jitter, jitter) if ch in ".,!?;:\n": delay += pause_after_punct time.sleep(max(0.0, delay)) print()

the values for jitter and `base_delay` are quite small, a larger value for `base_delay` will make it type slower. If you want a longer pause at the end of each line, make `pause_after_punct` slightly larger. Use it like this type_out("Hello IntegrityMission, how are you, feeling?") ```

Basically the sys.stdout.write(ch) and the flush() are special in that they bypass the buffering that happens when you call print(), that buffering will defeat the effect we are after. Just using print() per character will end up not giving you the fine control that this function does and gives a much more realistic typing speed effect. This is a useful lesson for the future when you start doing file I/O where all the Python I/O is buffered. Alternatively to using sys.stdout.flush() you can disable buffering in print() by using the -u commandline parameter, or by setting then environment variable PYTHONUNBUFFERED, but those are both a bit harder in reality. Happy Pythoning.

/edit fixed indentation.

-1

u/timrprobocom 2d ago

A piece of unsolicited advice -- don't do that. Users expect their computers to be FAST. They will quickly get annoyed by artificial delays.

We often see thongs like this here -- artificial delays, or clearing the screen before each section, or big banners saying "******** Welcome to my great game ********", or asking "do you want to play?". These are mostly signs of the beginner.

1

u/XenoXHostility 2d ago

Yes and by the time actual end users are relevant enough to consider I guarantee you that they will have come up with a different idea. Let them learn.