bzrr
bzrr

Reputation: 1530

How to wait some time in pygame?

While I've been using time.wait in my code since I began learning Python and Pygame, I've been wondering if there are any other ways to do it and what are the advantages and disadvantages of each approach. For example, Pygame also has a pygame.time.wait. What's the difference between python's wait and pygame's wait functions? Which one is better? And are there other ways to wait some time besides using these two functions?

Upvotes: 18

Views: 65449

Answers (3)

Rabbid76
Rabbid76

Reputation: 211278

If you just wait for some time, you can use pygame.time.wait or pygame.time.delay. However, if you want to display a message and then wait some time, you need to update the display beforehand. The display is updated only if either pygame.display.update() or pygame.display.flip() is called. See pygame.display.flip():

This will update the contents of the entire display.

Further you've to handles the events with pygame.event.pump(), before the update of the display becomes visible in the window. See pygame.event.pump():

For each frame of your game, you will need to make some sort of call to the event queue. This ensures your program can internally interact with the rest of the operating system.

This all means that you have to call pygame.display.flip() and pygame.event.pump() before pygame.time.delay() or pygame.time.wait():

screen.blit(text, (x, y))
pygame.display.flip()
pygame.event.pump()
pygame.time.delay(delay * 1000) # 1 second == 1000 milliseconds

See also Why doesn't PyGame draw in the window before the delay or sleep?


In any case, this 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.
For instance if you want to show a message on the display, get the current time and calculate the point in time after that the message has to disappear. Display the message as long as the current time is below the calculated time:

message_end_time = 0
run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    # [...]

    current_time = pygame.time.get_ticks()
    if something_has_happened:
        message_surf = font.render('Important message!', True, (255, 0, 0))
        message_end_time = pygame.time.get_ticks() + 3000 # display for 3 seconds

    window.fill(0)

    # [...]

    if current_time < message_end_time:
        window.blit(message_surf, (x, y))
    pygame.display.flip()

See also How do I stop more than 1 bullet firing at once?


Minimal example: PYGBAG demo repl.it/@Rabbid76/PyGame-MessageDelay

import pygame

pygame.init()
font = pygame.font.SysFont(None, 50)
text = font.render('press key or mouse', True, (255, 0, 0))

window = pygame.display.set_mode((500, 200))
clock = pygame.time.Clock()
message_end_time = pygame.time.get_ticks() + 3000

run = True
while run:
    clock.tick(60)
    current_time = pygame.time.get_ticks()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.KEYDOWN:
            text = font.render(pygame.key.name(event.key) + ' pressed', True, (255, 0, 0))
            message_end_time = pygame.time.get_ticks() + 2000
        if event.type == pygame.MOUSEBUTTONDOWN:
            text = font.render('button ' + str(event.button) + ' pressed', True, (255, 0, 0))
            message_end_time = pygame.time.get_ticks() + 2000

    window.fill(0)
    if current_time < message_end_time:
        window.blit(text, text.get_rect(center = window.get_rect().center))
    pygame.display.flip()

pygame.quit()
exit()

Upvotes: 5

ninMonkey
ninMonkey

Reputation: 7511

For animation / cooldowns, etc: If you want to 'wait', but still have code running you use: pygame.time.get_ticks

class Unit():
    def __init__(self):
        self.last = pygame.time.get_ticks()
        self.cooldown = 300    

    def fire(self):
        # fire gun, only if cooldown has been 0.3 seconds since last
        now = pygame.time.get_ticks()
        if now - self.last >= self.cooldown:
            self.last = now
            spawn_bullet()

Upvotes: 27

ljs.dev
ljs.dev

Reputation: 4493

For Python in general, you will want to look at the sleep library.

For Pygame, however, using pygame.time.delay() will pause for a given number of milliseconds based on the CPU clock for more accuracy (as opposed to pygame.time.wait).

Upvotes: 8

Related Questions