# Handling Events & User Event Limits In Pygame

I am trying to make a vertical shoot em up using Python and Pygame. In order to handle timing, such as when certain enemies come out and other stage events, I've been using pygame.time.set_timer().

For example, to start spawning simple enemies, I would do the following:

First setup a USEREVENT:

SPWNGRUNT = pygame.USEREVENT + 0


Then in the main loop, check for events:

for event in pygame.event.get():
if event.type == self.SPWNGRUNT:
spawnGrunt()


Then at some point, trigger the event on a timer:

pygame.time.set_timer(SPWNGRUNT, 600)


However, I have quickly ran out of these USEREVENTS. I eventually get the below error:

ValueError: Event id must be between NOEVENT(0) and NUMEVENTS(32)


My questions are this. Is there a way around this? Also, is there maybe a better way of managing timing and events that I am not seeing?

You can also use the time (delta time dt) that clock.tick(fps) returns to increase or decrease a timer variable.

import random
import pygame as pg

class Block(pg.sprite.Sprite):

def __init__(self, pos):
super().__init__()
self.image = pg.Surface((40, 40))
self.image.fill(pg.Color('sienna1'))
self.rect = self.image.get_rect(topleft=pos)

def main():
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
font = pg.font.Font(None, 30)
all_sprites = pg.sprite.Group()
# Delta time is the time that has passed since clock.tick
# was called the last time.
dt = 0
# We'll subtract dt (delta time) from this timer variable.
timer = 1  # 1 means one second.

done = False

while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True

# Decrease timer to get a countdown.
timer -= dt
# When the timer is below or equal to 0, we spawn
# a new block.
if timer <= 0:
random.randrange(440))))
# Reset the countdown timer to one second.
timer = 1
all_sprites.update()
screen.fill(pg.Color('gray15'))
all_sprites.draw(screen)
timer_surface = font.render(str(round(timer, 3)), True, pg.Color('yellow'))
screen.blit(timer_surface, (20, 20))

pg.display.flip()
# dt = time in seconds that passed since last tick.
# Divide by 1000 to convert milliseconds to seconds.
dt = clock.tick(60) / 1000

if __name__ == '__main__':
pg.init()
main()
pg.quit()


Another alternative would be to use pygame.time.get_ticks() to calculate the passed time.