How to make pygame update the display only upon an event?

Question:

I’m trying to do something like this.

pygame.event.set_allowed([pygame.KEYDOWN])
    for event in pygame.event.get():
        . . .
        pygame.display.flip()

Since the game I’m making is static when there’s no input anyway, I’m trying to avoid re-rendering identical frames between inputs in every single while True iteration. This code seems to be almost working, except there’s the slightest (disorienting) delay between input and result. If someone can help me mitigate this I want to go further and put much of the rest of the code within the for event in ... block to optimise a bunch more by skipping iterating over the game state 2D list every loop since it’s static until there’s input. Thank you.

Asked By: capyman1701

||

Answers:

To answer your title question:

while True:
    for event in pygame.event.get():
        if event.type == ...:
            # game updates
            # draw display
        pygame.display.flip()

However, that is indeed slow as game updates and drawing displays are called on every for-event-loop iteration. Perhaps you may want to refactor it to:

while True:
    for event in pygame.event.get():
        if event.type == ...:
            ...

    # game updates starts here

    # for keyboard presses
    keys = pygame.key.get_pressed()
    if keys[pygame.K_UP]:
        ...
   
    # draw display
    pygame.display.flip()

This way, the game update and drawing of display is called only once for every frame.

Answered By: Jobo Fernandez

The usual way is to update the game in every frame and to limit the frames per second using pygame.time.Clock.tick.

clock = pygame.time.Clock()
run = True
while run:
    for event in pygame.event.get():
        # handle events
        # [...]

    # clear background
    # [...]

    # draw scene   
    # [...]

    # update the display
    pygame.display.flip()

    # limit frames per second
    clock.tick(100)

If there is more than 1 event at once, your approach can update the game several times per frame. Sets a status variable when there was an event and updates the game once when the status is set:

run = True
while run:

    redraw_scene = False
    for event in pygame.event.get():
        redraw_scene = True
 
        # handle events
        # [...]

    if redraw_scene:
        # clear background
        # [...]

        # draw scene
        # [...]

        # update the display
        pygame.display.flip()
Answered By: Rabbid76
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.