Generar múltiples instancias del mismo objeto simultáneamente en Python

Resuelto awesomelej asked hace 4 años • 1 respuestas

Soy un programador principiante que está comenzando con Python y estoy comenzando creando un juego en pygame. Básicamente, el juego genera círculos en posiciones aleatorias y, cuando se hace clic, te otorga puntos.

Recientemente me encontré con un obstáculo cuando quiero generar varias instancias del mismo objeto (en este caso, círculos) al mismo tiempo. He probado cosas como sleep()y algún otro código relacionado con contadores, pero siempre da como resultado que el siguiente círculo generado anule el anterior (es decir, el programa genera el círculo 1, pero cuando entra el círculo 2, el círculo 1 desaparece).

¿Alguien sabe una solución para esto? ¡Realmente agradecería su ayuda!

import pygame
import random
import time

pygame.init()

window = pygame.display.set_mode((800,600))

class circle():
    def __init__(self, color, x, y, radius, width,):
        self.color = color
        self.x = x
        self.y = y
        self.radius = radius
        self.width = width

    def draw(self, win, outline=None):
        pygame.draw.circle(win, self.color, (self.x, self.y, self.radius, self.width), 0)

run=True
while run:
    window.fill((0, 0, 0))
    pygame.draw.circle(window, (255, 255, 255), (random.randint(0, 800),random.randint(0, 600)), 20, 20)
    time.sleep(1)
    pygame.display.update()

    for event in pygame.event.get():

        if event.type == pygame.QUIT:
            run=False
            pygame.quit()
            quit()
awesomelej avatar May 31 '20 14:05 awesomelej
Aceptado

No funciona de esa manera. time.sleep, pygame.time.wait()o pygame.time.delayno es la forma correcta de controlar el tiempo y el juego dentro de un bucle de aplicación. El juego no responde mientras esperas. El bucle de la aplicación se ejecuta continuamente. Tienes que medir el tiempo en el bucle y generar los objetos según el tiempo transcurrido.
pygame.Surface.fillborra toda la pantalla. Agregue los objetos recién creados a una lista. Vuelva a dibujar todos los objetos y la escena completa en cada cuadro.
Ver también Hora, evento del temporizador y reloj


Tienes 2 opciones. Úselo pygame.time.get_ticks()para medir el tiempo. Defina un intervalo de tiempo después del cual debería aparecer un nuevo objeto. Cree un objeto cuando se alcance el momento y calcule el momento para el siguiente objeto:

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())

Ejemplo mínimo:

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()

La otra opción es utilizar el pygame.eventmódulo. Úselo pygame.time.set_timer()para crear repetidamente un USEREVENTen la cola de eventos. El tiempo debe fijarse en milisegundos. p.ej:

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

Tenga en cuenta que en pygame se pueden definir eventos de clientes. Cada evento necesita una identificación única. Los identificadores de los eventos de usuario deben estar entre pygame.USEREVENT(24) y pygame.NUMEVENTS(32). En este caso pygame.USEREVENT+1es la identificación del evento para el evento del temporizador.

Reciba el evento en el bucle de eventos:

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

El evento del temporizador se puede detener pasando 0 al argumento de tiempopygame.time.set_timer de .

Ejemplo mínimo:

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()
Rabbid76 avatar May 31 '2020 07:05 Rabbid76