Search code examples
pythoneventstimerpygame

Timers and user events (PyGame)


My game is essentially flappy bird but with enemies, ammo (goatee's), and also flies instead of flaps (That part isn't necessary). I'm trying to figure out how to spawn the pipes in, the goatee's (ammo for the player to collect), and also the enemies. I've just learned about pygame.time.set_timer() today and I set it up with my pipes and it worked perfectly! That was until I created the goatee timer and then quickly found out that it won't set 2 separate timers. After looking over PyGames documentation I found this -

It is also worth mentioning that a particular event type can only be put on a timer once. In other words, there cannot be two timers for the same event type. Setting an event timer for a particular event discards the old one for that event type.

I've looked around and have not been able to find a way around this. Is there a way to create another event type? Is there a different way I should be using timers? Code listed below shows how I'm creating them:

Creating the timers:

    SPAWNPIPE = pygame.USEREVENT
    pygame.time.set_timer(SPAWNPIPE, 3000)

    SPAWNGOATEE = pygame.USEREVENT
    pygame.time.set_timer(SPAWNGOATEE, 6000)

Event handling inside the while loop:

#All game events
for event in pygame.event.get():
    if event.type == pygame.QUIT:
        pygame.quit()
        sys.exit()
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_SPACE and not time_started:
            is_playing = True
            time_started = True
            start_time = time.time()
    if event.type == SPAWNPIPE:
        spawn_pipe = True
    if event.type == SPAWNGOATEE:
        spawn_goatee = True

Even though pipe timer is set to 3000 milliseconds, they spawn at 6000 milliseconds because USEREVENT can only be used for one timer so the second one created overrides the first


Solution

  • Some google searching on creating custom events led me to the following SO question, PyGame Custom Event, as well as the following pygame docs, https://pyga.me/docs/ref/event.html#pygame.event.Event and https://pyga.me/docs/ref/event.html#pygame.event.custom_type.

    After writing a quick script to test this (copy/pasted below), it appears to work perfectly. Instead of using the same event type, create your own event type with pygame.event.custom_type()

    import pygame
    
    RED = (200, 100, 100)
    GREEN = (100, 200, 100)
    BLUE = (100, 100, 200)
    
    screen = pygame.display.set_mode((600, 400))
    
    screen.fill((255, 255, 255))
    pygame.display.flip()
    
    REDEVENT = pygame.event.custom_type()
    GREENEVENT = pygame.event.custom_type()
    BLUEEVENT = pygame.event.custom_type()
    
    pygame.time.set_timer(REDEVENT, 1000)
    pygame.time.set_timer(GREENEVENT, 1100)
    pygame.time.set_timer(BLUEEVENT, 1200)
    
    running = True
    while running:
        pygame.time.wait(10)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
                break
            if event.type == REDEVENT:
                screen.fill(RED)
                pygame.display.flip()
                continue
            if event.type == GREENEVENT:
                screen.fill(GREEN)
                pygame.display.flip()
                continue
            if event.type == BLUEEVENT:
                screen.fill(BLUE)
                pygame.display.flip()
                continue
    
    

    This would mean that, when creating your events, you should be using

        SPAWNPIPE = pygame.event.custom_type()
        pygame.time.set_timer(SPAWNPIPE, 3000)
    
        SPAWNGOATEE = pygame.event.custom_type()
        pygame.time.set_timer(SPAWNGOATEE, 6000)
    

    Logically the issue can be seen from your event handling, where SPAWNPIPE and SPAWNGOATEE were originally the same, so when you tested the type of the event, either event would actually trigger both event type checks

    CAVEAT:

    As @luke-b pointed out, Pygame- way to create more USEREVENT type events? mentions some specifics on the caveats of creating arbitrary user events, going into more detail than the docs do.

    Basically, you can only create a limited number of events (9 according to the SO answer) and pygame.event.custom_type() will raise an error if you try to create too many