在pygame中处理多个玩家关键输入的最有效方法是什么?

时间:2019-10-21 21:53:28

标签: python pygame

我正在用pygame编写游戏,当时在徘徊什么是处理多个玩家键输入的最佳方法,例如在乒乓游戏中,您可以为一个玩家处理“ w,s”键的键输入和另一个的箭头键。

我现在的操作方式是在Player类中使用一个名为“ control_type”的变量,该变量在初始化每个播放器时分配。然后在Player类中,我检查变量是否等于'wasd'或'arrows',然后相应地检查键输入。它可以工作,但有时似乎滞后并跳过了一些帧。是这样做的好方法还是更好的处理方法?

2 个答案:

答案 0 :(得分:3)

您可以这样做,但是如果您说

  

但有时似乎会滞后并跳过一些帧

记住一件事(因为这是一个常见的错误):

每帧只能调用一次pygame.event.get()。如果按下某个键并将事件添加到队列中,并且您呼叫pygame.event.get()并且不处理该事件,则该事件将丢失,并且对pygame.event.get()的另一次调用将不会收到该事件。

我使用的一种常见模式是将一帧的所有事件存储在列表中,并在多个位置使用该列表来检查当前代码感兴趣的事件。使用Sprite类时,您可以简单地将该列表传递到您的Group,以将其向下传递到精灵。

简化示例:

...
sprites = pygame.sprite.Group()

while True:
    events = pygame.event.get()
    for e in events:
        ... handle "global" events like QUIT

    sprites.update(events) # pass events to all sprites

然后在sprite类中

class Foo(pygame.sprite.Sprite):
   ...
   def update(self, events):
       for e in events:
           ... handle other events

需要注意的另一件事:在类似Pong的游戏中,您按住某个键进行移动,您可能对单个键事件不感兴趣,而对键的当前状态感兴趣(是否按下了键?) 。因此,您想调用pygame.key.get_pressed()来获取键盘的状态。多次拨打pygame.key.get_pressed()很好。

另一个简化的伪示例:

class Paddle(pygame.sprite.Sprite):
    def __init__(self, pos, up_key, down_key, *grps):
        super().__init__(*grps)
        self.image = ...
        self.rect = ...
        self.up_key = up_key
        self.down_key = down_key

    def update(self):
        pressed = pygame.key.get_pressed()
        if pressed[self.up_key]:  self.rect.move_ip(0, -1)
        if pressed[self.up_down]: self.rect.move_ip(0,  1)

并初始化多个玩家,例如:

sprites = pygame.sprite.Group()
Player(p1, pygame.K_w, pygame.K_s, sprites)
Player(p2, pygame.K_UP, pygame.K_DOWN, sprites)

答案 1 :(得分:0)

我成功使用的一种方法是每当调用pygame.event.get()时,如果需要在其他地方拉出事件,只需将其放回队列即可。例如

for event in pygame.event.get():
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_UP:
            handle_up()
        # Check for all your other relevant keys...

        elif event.key == pygame.K_w: # Or any key you need elsewhere
            pygame.event.post(event) # Put it back on the queue

您需要注意这一点,因为将过多的内容放回队列可能导致队列填满。但是,如果您放回队列中的所有内容肯定会在其他地方使用,那么您就很好了。