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

Solution 1:

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.

If you want to display a text and delay the game, then you've to update the display and handle the events.

Write a function which delays the game and updates the display. I recommend to use the pygame.time module to implement the delay (e.g. pygame.time.delay())

def update_and_wait(delay):
    pygame.display.flip()
    pygame.event.pump()
    pygame.time.delay(delay * 1000) # 1 second == 1000 milliseconds

Or even implement a function which its own event loop to keep the application responding. Measure the time by pygame.time.get_ticks():

def update_and_wait(delay):
    start_time = pygame.time.get_ticks()
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                print("auit")
                pygame.quit()
                return False
        if pygame.time.get_ticks() >= start_time + delay * 1000: 
            break
    return True

Use the function in the application:

def main():
    # [...]

    while not done:
        # [...]

        for ball in ball_list:
            # [...]

            if right_score == 0:
                message_wait("RIGHT PLAYER HAS WON!!", white, 300, 200, font, game_win)
                update_and_wait(5)
                quit()
            elif left_score == 0:
                message_wait("LEFT PLAYER HAS WON!!", white, 300, 200, font, game_win)
                update_and_wait(5)
                quit()