【问题标题】:Why doesn't this loop run properly?为什么这个循环不能正常运行?
【发布时间】:2018-07-16 11:09:38
【问题描述】:
while g.running:
    for event in pygame.event.get():
        if event == pygame.QUIT:
            g.running = False
    g.run(Player_1)

quit()

当我运行这个循环时,它会完全跳过 for 循环,或者只执行一次,而且速度太快,我无法运行,它会继续运行。如何使循环正常工作? https://github.com/maartenww/100daysOfCode_projectOne

此外,g.run 基本上所做的只是更新游戏。所以它会绘制和/或移动所有精灵,将文本绘制到屏幕上并进行一些计算

class Game:
    def __init__(self):
        self.running = True

    def run(self, player_1):
        self.border_col(player_1)
        self.load_text(player_1)
        self.update_game(player_1)

    def update_game(self, player_1):
        clock.tick(FPS)
        gameDisplay.fill(black)
        gameDisplay.blit(self.xcolon, (0, 0))
        gameDisplay.blit(self.actual_x, (25, 0))
        gameDisplay.blit(self.ycolon, (0, 30))
        gameDisplay.blit(self.actual_y, (25, 30))
        gameDisplay.blit(self.acolon, (0, 60))
        gameDisplay.blit(self.actual_a, (25, 60))
        gameDisplay.blit(self.vcolon, (0, 90))
        gameDisplay.blit(self.actual_v, (25, 90))
        all_sprites.draw(gameDisplay)
        Player.move_player(player_1)
        Player.update_player(player_1)
        pygame.display.update()

【问题讨论】:

  • 你能把它缩小到一个更小的可重现的例子吗?
  • @doctorlove 你是什么意思?
  • 就目前而言,您发布的代码并没有告诉我g 是什么。当然,有些人可以去阅读你的 github 代码。但是,问题不是自包含的。如果您更改 github 上的代码,那么这个问题对未来的人们将毫无意义。您能否包含一个具有相同行为的 Game 类的简化版本?
  • 还有一个问题 - 您期待哪些事件? g.run 行是否被一遍又一遍地调用,但你只得到一个事件(最多)?或者你是说它掉到quit
  • @doctorlove 啊现在我明白了,当然

标签: python loops pygame exit


【解决方案1】:

我查看了你的 repo,相关代码是这样的,在 player.py:

def move_player(self):
    for event in pygame.event.get():
        # Player movement
        if (event.type == pygame.KEYDOWN):
            if (event.key == pygame.K_d):
                self.player_acc = PLAYER_ACC

            if (event.key == pygame.K_a):
                self.player_acc = -PLAYER_ACC

        if (event.type == pygame.KEYUP):
            if (event.key == pygame.K_d):
                self.player_acc = 0

            if (event.key == pygame.K_a):
                self.player_acc = 0

想想你的主循环中发生了什么:

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

您从事件队列中获取所有事件,将其清除,然后检查QUIT

然后你调用g.run,它会调用self.update_game,它会调用Player.move_player,它会再次从事件队列中获取所有事件并清除它。

所以当QUIT 事件在事件队列中时pygame.event.get()Player.move_player 内部被调用时,它实际上丢失了,因为您没有在这个for 循环中处理它。当在main 中再次调用pygame.event.get() 时,QUIT 事件不再在队列中(因为调用event.get 会清除队列)。

基本上,每次主循环迭代只应调用一次“event.get”(pygame.display.flip/pygame.display.update 也是如此)。

也许将main 中的循环改成这样:

while g.running:
    for event in pygame.event.get():
        g.handle(event, Player_1)
    g.run(Player_1)

将此添加到Game

def handle(self, event, player_1):
    if event.type == pygame.QUIT:
        self.running = False
    else:
        player_1.handle(event)

这个给Player:

def handle(self, event):
    # Player movement
    if (event.type == pygame.KEYDOWN):
        if (event.key == pygame.K_d):
            self.player_acc = PLAYER_ACC

        if (event.key == pygame.K_a):
            self.player_acc = -PLAYER_ACC

    if (event.type == pygame.KEYUP):
        if (event.key == pygame.K_d):
            self.player_acc = 0

        if (event.key == pygame.K_a):
            self.player_acc = 0

并删除Player.move_player

【讨论】:

  • 我改变了它,但它给出了这个错误: Traceback (last recent call last): File "C:/ScrewAround/100DaysOfCodeProject1/main.py", line 103, in main() File “C:/ScrewAround/100DaysOfCodeProject1/main.py”,第 98 行,在主 g.run(Player_1) 文件中“C:/ScrewAround/100DaysOfCodeProject1/main.py”,第 58 行,在运行 self.update_game(player_1) 文件中“C:/ScrewAround/100DaysOfCodeProject1/main.py”,第 50 行,在 update_game Player.handle(player_1) 类型错误:handle() 缺少 1 个必需的位置参数:'event'
  • update_game 中删除Player.handle(player_1)。看看我的答案中的代码。主循环调用g.handle(event, Player_1)Game.handle调用player_1.handle(event)
  • 但是精灵不再移动了。
  • @Maartenww 是的,if (event.type == pygame.QUIT): 行也应该从主循环中删除。我的错。我改变了答案。
  • 非常感谢,我现在明白答案了。感谢您的努力。@sloth
【解决方案2】:

我预计循环确实会运行,但您遇到了类型不匹配未报告的情况。

for event in pygame.event.get():
    if event == pygame.QUIT:

event 将是一个 pygame.event.Event 对象。您要检查的QUIT 值是可能出现在event.type 属性中的值。由于没有事件是整数值QUIT,所有事件都被忽略。您可能想要添加一个else 子句来诊断哪些事件已接收但未处理。

【讨论】:

  • 我添加了一个 else 语句并让它打印事件。我发现它非常不规则地运行循环。换句话说,它只有在您无法计时的特定时间单击 x 按钮时才有效。
  • 我相信树懒找到了原因(我没有彻底挖掘源代码库)。
  • @YannVernier 您的回答也是有效的,因为问题中的代码显然有您在回答中描述的错误;但它在 github repo 中是正确的。
猜你喜欢
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
  • 2012-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-26
相关资源
最近更新 更多