1

I have this piece of code in the end of my main function in a python pygame script. This seems to be the correct way to handle an exit with a simple keypush.

running = True
while running == True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
            break
        elif event.type == pygame.KEYDOWN:
            running = False
            break
    if running == False:
        break

    draw(screen, background)

pygame.quit()  # quits pygame
sys.exit()

However in this draw function I also have the following line right before the closing accolade:

pygame.time.delay(randint(2,5) * 1000)

This line of code makes the game wait anywhere from 2 till 5 seconds. Apparently this delay code creates an extra delay of about 3 loops in detecting the key pushes.

My question is: how do I properly execute an immediate exit with a key push without waiting for the delay?


Edit: Solution (credit to Håken Lid)

animate_event = pygame.USEREVENT
pygame.time.set_timer(animate_event, 1000)

while True:
    if pygame.event.get(pygame.QUIT): break
    if pygame.event.get(pygame.KEYDOWN): break

    for event in pygame.event.get():
        if event.type == animate_event:
            animate(screen, background)
            # reset event
            pygame.time.set_timer(animate_event, randint(2,5)*1000)

pygame.quit()
sys.exit()
Michel Michels
  • 1,820
  • 2
  • 12
  • 17
  • 2
    Use `set_timer` instead of `delay`. That will not block the event loop. See this question for details. https://stackoverflow.com/questions/23368999/move-an-object-every-few-seconds-in-pygame/23384291 – Håken Lid Aug 28 '17 at 09:55
  • 1
    Long story short: never pause the graphical thread, for it will pause the event processing as well. – Right leg Aug 28 '17 at 10:37
  • @HåkenLid Thanks! This seems indeed the solution to my problem! – Michel Michels Aug 28 '17 at 10:45
  • @Rightleg How should I do little animations? Also with events? I have an animation that flips an image which simple rescales the image and repaints it in a for loop with some delay in it so humans can see what happens. Is this the right way or should I somehow rewrite this with events? – Michel Michels Aug 28 '17 at 10:47
  • I'd do something with coroutines/generators. Suppose you have an `animation` function, that updates some sprite in a `for` or `while` loop. At the end of the loop (in the block), put a `yield` - this means "stop here until you're told to resume". Then in your main code, create a generator out of this function: `animator = animation()`. Then inside of your main loop, update this animator at each iteration: `next(animator)` - this means "resume (or start) and run until the next `yield`". But it's a bit too complicated to be detailed in a mere comment, even in a full answer... – Right leg Aug 28 '17 at 12:06
  • @MichelMichels you should post another question instead of asking in the comments. But check out the other questions about animations on SO first. – skrx Aug 28 '17 at 17:40

0 Answers0