Spawning multiple instances of the same object concurrently in python

It does not work that way. time.sleep, pygame.time.wait() or pygame.time.delay is not the right way to control time and gameplay within an application loop. The game does not respond while you wait. The application loop runs continuously. You have to measure the time in the loop and spawn the objects according to the elapsed time.
pygame.Surface.fill clears the entire screen. Add the newly created objects to a list. Redraw all of the objects and the entire scene in each frame.
See also Time, timer event and clock


You have 2 options. Use pygame.time.get_ticks() to measure the time. Define a time interval after which a new object should appear. Create an object when the point in time is reached and calculate the point in time for the next object:

object_list = []
time_interval = 500 # 500 milliseconds == 0.1 seconds
next_object_time = 0 

while run:
    # [...]
    
    current_time = pygame.time.get_ticks()
    if current_time > next_object_time:
        next_object_time += time_interval
        object_list.append(Object())

Minimal example:

repl.it/@Rabbid76/PyGame-TimerSpawnObjects

import pygame, random
pygame.init()
window = pygame.display.set_mode((300, 300))

class Object:
    def __init__(self):
        self.radius = 50
        self.x = random.randrange(self.radius, window.get_width()-self.radius)
        self.y = random.randrange(self.radius, window.get_height()-self.radius)
        self.color = pygame.Color(0)
        self.color.hsla = (random.randrange(0, 360), 100, 50, 100)

object_list = []
time_interval = 200 # 200 milliseconds == 0.2 seconds
next_object_time = 0 

run = True
clock = pygame.time.Clock()
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
    
    current_time = pygame.time.get_ticks()
    if current_time > next_object_time:
        next_object_time += time_interval
        object_list.append(Object())
    
    window.fill(0)
    for object in object_list[:]:
        pygame.draw.circle(window, object.color, (object.x, object.y), round(object.radius))
        object.radius -= 0.2
        if object.radius < 1:
            object_list.remove(object)
    pygame.display.flip()

pygame.quit()
exit()

The other option is to use the pygame.event module. Use pygame.time.set_timer() to repeatedly create a USEREVENT in the event queue. The time has to be set in milliseconds. e.g.:

object_list = []
time_interval = 500 # 500 milliseconds == 0.1 seconds
timer_event = pygame.USEREVENT+1
pygame.time.set_timer(timer_event, time_interval)

Note, in pygame customer events can be defined. Each event needs a unique id. The ids for the user events have to be between pygame.USEREVENT (24) and pygame.NUMEVENTS (32). In this case pygame.USEREVENT+1 is the event id for the timer event.

Receive the event in the event loop:

while run:
    for event in pygame.event.get():
        if event.type == timer_event:
            object_list.append(Object())

The timer event can be stopped by passing 0 to the time argument of pygame.time.set_timer.

Minimal example:

repl.it/@Rabbid76/PyGame-TimerEventSpawn

import pygame, random
pygame.init()
window = pygame.display.set_mode((300, 300))

class Object:
    def __init__(self):
        self.radius = 50
        self.x = random.randrange(self.radius, window.get_width()-self.radius)
        self.y = random.randrange(self.radius, window.get_height()-self.radius)
        self.color = pygame.Color(0)
        self.color.hsla = (random.randrange(0, 360), 100, 50, 100)

object_list = []
time_interval = 200 # 200 milliseconds == 0.2 seconds
timer_event = pygame.USEREVENT+1
pygame.time.set_timer(timer_event, time_interval)

run = True
clock = pygame.time.Clock()
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        elif event.type == timer_event:
            object_list.append(Object())
    
    window.fill(0)
    for object in object_list[:]:
        pygame.draw.circle(window, object.color, (object.x, object.y), round(object.radius))
        object.radius -= 0.2
        if object.radius < 1:
            object_list.remove(object)
    pygame.display.flip()

pygame.quit()
exit()

Leave a Comment