【问题标题】:Spawning multiple instances of the same object concurrently in python在python中同时产生同一个对象的多个实例
【发布时间】:2022-12-10 04:40:36
【问题描述】:

我是一个初学者,从 python 开始,我开始用 pygame 制作游戏。 该游戏基本上会在随机位置生成圆圈,单击后会为您提供积分。

最近,当我想同时生成同一对象(在本例中为圆圈)的多个实例时,我遇到了障碍。 我已经尝试过 sleep() 之类的东西以及其他一些与计数器相关的代码,但它总是导致下一个圆圈覆盖前一个圆圈(即程序生成圆圈 1,但是当圆圈 2 出现时,圆圈 1 消失)。

有谁知道这个的解决方案?我将衷心感谢您的帮助!

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

【问题讨论】:

    标签: python loops oop object pygame


    【解决方案1】:

    它不是那样工作的。 time.sleeppygame.time.wait()pygame.time.delay 不是在应用程序循环中控制时间和游戏玩法的正确方法。在您等待时游戏没有响应。应用程序循环连续运行。您必须测量循环中的时间并根据经过的时间生成对象。
    pygame.Surface.fill 清除整个屏幕。将新创建的对象添加到列表中。重绘每一帧中的所有对象和整个场景。
    另见Time, timer event and clock


    你有两个选择。使用pygame.time.get_ticks()来测量时间。定义新对象出现的时间间隔。到达时间点时创建一个对象,计算下一个对象的时间点:

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

    最小的例子:

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

    另一种选择是使用pygame.event 模块。使用pygame.time.set_timer()在事件队列中重复创建USEREVENT。时间必须以毫秒为单位设置。例如。:

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

    注意,在 pygame 中可以定义客户事件。每个事件都需要一个唯一的 ID。用户事件的 ID 必须介于 pygame.USEREVENT (24) 和 pygame.NUMEVENTS (32) 之间。在这种情况下,pygame.USEREVENT+1 是定时器事件的事件 ID。

    在事件循环中接收事件:

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

    可以通过将 0 传递给时间pygame.time.set_timer 的参数。

    最小的例子:

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

    【讨论】:

    • 非常感谢你的帮助!我真的很感激它,哈哈,它对我学习这门新语言有很大帮助。另外,非常感谢您帮助更改和优化其他代码,例如圆圈生成的位置,这是一个非常聪明的功能!谢谢!
    猜你喜欢
    • 2020-09-18
    • 1970-01-01
    • 2013-01-18
    • 2012-01-13
    • 1970-01-01
    • 2020-10-25
    相关资源
    最近更新 更多