【问题标题】:Pygame hold key down causes an infinite loop [duplicate]Pygame按住键会导致无限循环[重复]
【发布时间】:2013-11-23 01:18:18
【问题描述】:

我正在尝试编写一个 Pong 游戏,我可以在其中使用向上和向下箭头移动球拍。我创建了一个 Paddle 对象,每次按下向上键时都会更新给定的数量(在下面的代码中作为参数“num”传递)。我想要做的是允许用户按住向上按钮,这将导致桨持续向上移动。我尝试在 while 循环中编写此事件处理,但我陷入了无限循环。下面是代码:

    for event in PE.get():
        if event.type == PG.KEYDOWN:
            keystate = PG.key.get_pressed()
            if event.key == PG.K_ESCAPE:
                done = True
            while keystate[PL.K_UP]:
                rightPaddle.update(-20)


        if event.type == PG.QUIT:
            done = True

下面是 Paddle 对象的代码:

    class Paddle(object):

def __init__(self, x, y):
    self.topleftx = x
    self.toplefty = y
    self.width = 15
    self.height = 100

def draw(self, surface):
    rect = PR.Rect(self.topleftx, self.toplefty, \
                        self.width, self.height)
    surface.fill(WHITE, rect)

def update(self, num):
    self.toplefty += num

我检查了有关此主题的其他 stackoverflow 问题,这就是我找到 PG.key.getPressed() 方法的方式,但其他答案建议使用我不确定如何使用的“精灵”。任何人都可以就如何执行此任务提供一些建议吗?

【问题讨论】:

    标签: python pygame


    【解决方案1】:

    while 循环的问题在于它正在评估一个 keydown 事件。该事件将永远是它开始时的任何内容,并且它没有机会在事件处理代码中更改。您要捕获的是紧随其后的 PG.KEYUP 事件。所以你会有一些(逻辑上)像

    if event.type == PG.KEYDOWN and keystate[PL.K_UP]:
        key_up_pressed = True
    elif event.type == PG.KEYUP and keystate[PL.K_UP]:
        key_up_pressed = False
    

    显然,您可以更好地考虑这一点,但 key_up_pressed 状态将在您的主循环中每隔一段时间(帧、毫秒等)被评估一次,然后移动桨。

    【讨论】:

    • 我还是有点困惑。我理解为什么现在会发生无限循环,但我似乎无法想出解决它的方法。即使我定义了一个 key_up_pressed 变量,我应该把 update() 方法放在哪里?是否仍应在事件驱动的 for 循环中?
    • 不,它应该在程序的主循环中。 SDL(和 Pygame)程序通常由处理事件、绘制到屏幕并执行需要做的事情(更新物理等)的主循环构成。您希望将其放入其中,以便可以经常更新。一旦它朝着正确的方向移动,请尝试将其与帧速率分离。
    【解决方案2】:

    在这段代码中:

    while keystate[PL.K_UP]:
        rightPaddle.update(-20)
    

    ...没有什么可以改变keystate。所以,如果keystate[PL.K_UP] 一次为真,它将永远为真。因此是无限循环。

    您可以每次通过循环从 pygame 获取当前的密钥信息,这至少不会使其无限——但这仍然意味着您的整个程序会阻塞,直到用户释放密钥。

    在不知道您打算编写帧速率驱动游戏还是事件循环驱动游戏的情况下,我无法确切告诉您如何解决它。

    但无论哪种方式,关键是你不想一遍又一遍地移动,只要按住键,你想以一定的速度移动,处理中间的其他事件,只要键被按住。无论哪种方式,您都将使用 KEYDOWN 和 KEYUP 事件来设置某种标志,告诉您移动桨。然后,每帧一次,或使用计时器事件,或以其他方式,您将使用当前标志值来移动桨。

    【讨论】:

      猜你喜欢
      • 2013-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-07
      • 1970-01-01
      • 2016-05-01
      • 1970-01-01
      • 2013-12-12
      相关资源
      最近更新 更多