Pygame 事件队列

4 投票
3 回答
4925 浏览
提问于 2025-04-17 10:16

我想知道有没有办法使用 poll()get() 而不把事件从队列中移除。

在我的游戏里,我在不同的地方检查输入(不仅仅是在主循环里),有时候我需要在不同的地方检查同一个事件,但当我检查一次后,它就会从队列中被移除。我试过使用 peek(),但问题是我无法获取与事件对应的按键。

while 1:
    event = pygame.event.poll()
    if event.type == KEYDOWN:
        return event.key
    else:
        pass

#works but removes event from the queue

这个方法可以获取与事件对应的按键,但使用 peek() 就不行:

pygame.event.peek(pygame.KEYDOWN).key 
#dosent work

不过我不能使用第一个方法,因为它会把事件从队列中移除,这样我就不能在程序的其他地方检查按键事件了。
我对 queue 是怎么工作的理解不太清楚,也许我只是搞错了,但我在不同的位置尝试了第一个方法,只有第一次检查事件时它有效。

我的目标是在游戏的不同类中检查事件。

谢谢你的帮助

3 个回答

0

根据我的理解,这里没有一种“正确”的方法来处理这个问题,但有一个选择是把所有的事件保存到一个变量里。这样你就可以随时访问这些事件,想用多少次都可以。

0

我不知道这样做是不是好风格,但我做的就是把所有的事件都保存在一个变量里,然后把这个变量传给那些使用自己事件队列的对象,让它们来检测“它们自己的”事件。

while running:
        events = pygame.event.get()
        for event in events:
            if event.type == pygame.QUIT:
                running = False

        self.allS.update(events)

然后在更新方法里:

for event in events:
    print("Player ", event)
4

我觉得一个更好的设计方式是把事件检查放在一个地方——即使是放在一个单独的函数或方法里,而不是主循环代码中。然后把所有相关的事件数据保存在其他对象(作为属性)或变量里。

举个例子,你可以保存一个Python集合,里面记录所有当前按下的键、当前鼠标的位置和按钮状态,然后把这些变量传递给其他函数和方法。

如果你只需要检查按下的键和鼠标状态(还有指针位置),你可以完全不处理事件(只在主循环中调用一次pygame.event.pump())。我最喜欢的读取键盘的方法是使用pygame.key.get_pressed函数——它会返回一个序列,序列的长度和键码数量一样,每个被按下的键在这个序列中对应的位置会被设置为True。(键码可以在pygame.locals中找到,比如K_ESC、K_a、K_LEFT等等)。

例如:

if pygame.key.get_pressed()[pygame.K_ESCAPE]:
     pygame.quit()

鼠标模块(详细信息可以在http://www.pygame.org/docs/ref/mouse.html找到)也允许你获取鼠标状态,而不需要消耗事件。

最后,如果你真的想获取事件,我认为可以把未被处理的事件重新放回队列,使用pygame.event.post这个调用——这个调用可以放在一个if/elif序列的else部分,那里你可以检查事件队列中的某些状态。

撰写回答