How to run multiple while loops at a time in Python

No, that’s not the way it goes. You have an application loop so use it. time.sleep, pygame.time.wait() or pygame.time.delay is not the way to wait or delay something in a typical application. The game does not respond while you wait. Use pygame.time.get_ticks() to measure the time.

In pygame the system time can be obtained by calling pygame.time.get_ticks(), which returns the number of milliseconds since pygame.init() was called. See pygame.time module.

Calculate the point in time when the text needs to be changed. Get a new random text and render the text Surface after the current time is greater than the calculated point of time. Calculate a new random point in time which is greater than the current time:

next_render_time = 0

while run:
    current_time = pygame.time.get_ticks()

    # [...]

    if current_time >= next_render_time:
        currentFace = random.choice(face)
        faceDisplay = myFont.render(str(currentFace), 1, (0,255,0))
        next_render_time = current_time + randint(5, 10) * 1000

    screen.fill((0,0,0))
    screen.blit(faceDisplay, text_rect)
    pygame.display.flip()

The time is multiplied by 1000 (randint(5, 10) * 1000), since the time unit of pygame.time.get_ticks() is milliseconds.

Actually, you can also use a timer event. See How do I use a PyGame timer event?.
In your case, however, the time interval is not constant. It’s a bit odd to use a timer event on a dynamically changing interval. I would prefer to use a timer event for an action that needs to be performed at constant intervals. But that’s just my opinion.


Complete example:

from random import randint
from time import sleep
import pygame
import pygame.freetype
import time
import random
run = True
pygame.init()

#faces
face = ['^-^', '^v^', '◠◡◠', "'v'", '⁀◡⁀']
talkingFace = ['^o^', '^▽^', '◠▽◠', "'▽'", '⁀ᗢ⁀']
currentFace = random.choice(face)

#background
screen = pygame.display.set_mode((800,600))

#font and size
myFont = pygame.font.Font('unifont.ttf', 100)

#face render
faceDisplay = myFont.render(str(currentFace), 1, (0,255,0))

#center and draw face
text_rect = faceDisplay.get_rect(center=(800/2, 600/2))

next_render_time = 0

#prevent crashes
while run:
    current_time = pygame.time.get_ticks()
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            run = False
 
    if current_time >= next_render_time:
        currentFace = random.choice(face)
        faceDisplay = myFont.render(str(currentFace), 1, (0,255,0))
        next_render_time = current_time + randint(5, 10) * 1000

    screen.fill((0,0,0))
    screen.blit(faceDisplay, text_rect)
    pygame.display.flip()

Leave a Comment