【问题标题】:Pygame : Having trouble w/ multiple event.get() calls [duplicate]Pygame:在多个 event.get() 调用时遇到问题 [重复]
【发布时间】:2021-05-01 12:26:49
【问题描述】:

我目前正在 Pygame 中制作飞机射击游戏。我已经创建了平面类,现在开始创建子弹类。但是,我遇到了一个我无法解决的问题: 我真的需要在类内部和 while 循环(游戏的主 while 循环)中使用 pygame.event.get() 循环。因此,当我使用 2 个这样的循环时,游戏控件变得如此怪异和混乱,在我搜索此问题后,我发现通常它必须只有 pygame.event.get() 上的一个循环。我不知道该怎么做,因为如果我将两个循环组合到位于 while 循环中的主循环中,那么我将无法引用项目符号对象,因为它将在类之外。 这是我的代码:

class Singlebullet(object):

    def __init__(self):
        self.img = pygame.image.load(r'C:\Users\me\Documents\MyGame\bullet.png')
        self.x = planeX + 71 
        self.y = planeY 
        self.state = 'ready'
        self.speed = 0
        self.firerate = 1000
    
    def shoot(self):
        if current_bullet_type == 'single':
            if self.state == 'ready':
                MyScrollingScreen.blit(self.img, (self.x, self.y))
            if self.state == 'fire':
                self.speed = -8
                self.y += bullet_speed
                MyScrollingScreen.blit(self.img, (self.x, self.y))
            if self.y < -20:
                self.state = 'ready'
            for e in pygame.event.get():
                if e.type == pygame.KEYDOWN or e.type == pygame.KEYUP:
                    if e.key == pygame.K_SPACE:
                        self.state = 'fire'
                        pygame.time.set_timer(pygame.USEREVENT+1, self.firerate)
                if e.type == pygame.USEREVENT+1:
                    self.state = 'ready'
s1 = Singlebullet()

while running:
    #[...]
    for event in pygame.event.get():
        #[...]

【问题讨论】:

    标签: python loops oop pygame


    【解决方案1】:

    pygame.event.get() 从队列中移除事件(参见pygame documentation)。

    所以,一些事件是在主循环中获取的,而其他事件是在类中获取的,并且您不知道特定事件是从哪里获取的 py pygame.所以你错过了一些事件。

    为避免这种情况,每帧调用一次pygame.event.get(),并对主循环和SingleBullet使用相同的列表:

    class Singlebullet(object):
        
        def shoot(self):
            ...
            for e in events: # same events as in main loop
    
    while running:
        events = pygame.event.get()
        for event in events:
            ...
    

    如果您在调用Singlebullet.shoot() 后获得事件,请不要忘记将列表设置为第一帧[](该类将要求提供一个不存在的列表)。

    【讨论】:

    • 谢谢,它正在工作!但是你说的最后一句话是什么意思?我没听懂
    • @Developeeer "...最后一句话是什么意思..." - 在这种方法中,events 是一个全局变量。在第一次调用 shoot() 之前,您必须确保设置了 events
    • events 是在主循环中定义的变量。如果你在程序开始时调用SingleBullet.shoot(),而不启动主循环,那么events是没有定义的。避免这种情况的一种简单方法是在调用shoot() 之前定义events = [](在本例中用于第一帧)
    【解决方案2】:

    pygame.event.get() 获取所有消息并将它们从队列中删除。请参阅文档:

    这将获取所有消息并将它们从队列中删除。 [...]

    如果在多个事件循环中调用pygame.event.get(),则只有一个循环接收事件,但并非所有循环都接收所有事件。因此,似乎错过了一些事件。

    每帧获取一次事件并在多个循环中使用它们或将事件列表传递给处理它们的函数和方法:

    class Singlebullet(object):
    
        def __init__(self):
            # [...]
        
        def shoot(self, event_list):
            if current_bullet_type == 'single':
                # [...]
    
                for e in event_list:
                    if e.type == pygame.KEYDOWN or e.type == pygame.KEYUP:
                        if e.key == pygame.K_SPACE:
                            self.state = 'fire'
                            pygame.time.set_timer(pygame.USEREVENT+1, self.firerate)
                    if e.type == pygame.USEREVENT+1:
                        self.state = 'ready'
                        
    s1 = Singlebullet()
    
    while running:
        #[...]
    
        event_list = pygame.event.get()
        for event in event_list:
            #[...]
    
        s1.shoot(event_list)
    

    【讨论】:

    • 谢谢!但我没有得到最后一行
    • @Developeeer 你在某个地方叫shoot(),不是吗? (我不知道您在哪里执行此操作,因为您的问题中缺少该部分)。您必须将event_list 传递给def shoot(self, event_list)。另一种解决方案是使用其他答案中的全局变量。然而,这是一个非常糟糕和丑陋的设计。
    • 好吧,现在很清楚了,谢谢!
    猜你喜欢
    • 2015-06-19
    • 2018-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多