2

我正在使用 Pygame 制作一个简单的游戏,您必须在其中获得(通过将光标移到它们上方)将出现在屏幕上的所有圆圈(每秒会出现更多圆圈)。代码很长,所以我做了一个示例代码。此代码工作正常,Pygame 窗口根本不会变得无响应:

import pygame, random, sys

pygame.init()

window=pygame.display.set_mode((480,360))

end_program=False
while not end_program:
    for event in pygame.event.get():
        if event.type==pygame.QUIT  or  pygame.key.get_pressed()[pygame.K_ESCAPE]: #If the user either click the "x", or pressed the "esc" key
            end_program=True

    pass

pygame.quit()
sys.exit()

但是,在我的游戏中,为了让用户可以选择再次玩,我需要将所有内容包装end_program在另一个循环中。在显示的示例中,这是break_from_second_loop

import pygame, random, sys

pygame.init()

window=pygame.display.set_mode((480,360))

end_program=False
while not end_program:
    for event in pygame.event.get():
        if event.type==pygame.QUIT  or  pygame.key.get_pressed()[pygame.K_ESCAPE]: #If the user either click the "x", or pressed the "esc" key
            end_program=True

    break_from_second_loop=False

    while not break_from_second_loop:
        pass

pygame.quit()
sys.exit()

现在,如果运行它,窗口将变得无响应!任何人都知道为什么像将代码包装在另一个循环中(根本不改变代码)这样​​简单的事情会这样做吗?

4

2 回答 2

3

问题是,如果您没有运行事件循环,游戏将无法响应,或者根本无法执行任何操作。在另一个循环中,您没有运行事件循环。

这是基于事件循环的编程的普遍问题。你不能做任何需要很长时间的事情,你不能做任何必须跨越多个事件的事情。

因此,您必须将循环分成多个步骤,并且每次通过事件循环只执行一个步骤(或其中几个步骤)。

在这种特殊情况下,它实际上非常简单:只需将其更改whileif(并将主循环移到has_got_all_circles=False外部),您的逻辑现在每次通过事件循环都运行一次。

或者,将其更改为 anif并将移动到 中for,因此现在它每个事件只运行一次,而不是每个事件循环迭代一次。

第三种选择是将整个事物分解为一个函数并将其设置为空闲或计时器函数,该函数在事件循环空闲时运行,或每帧一次,或每 20 毫秒一次,或其他任何时间。

很难知道这三个中哪一个适合您的情况,但基本思想在所有这些中都是相同的,所以我只展示第二个:

end_program=False
break_from_second_loop=False
while not end_program:
    for event in pygame.event.get():
        if event.type==pygame.QUIT  or  pygame.key.get_pressed()[pygame.K_ESCAPE]: #If the user either click the "x", or pressed the "esc" key
            end_program=True
        if not break_from_second_loop:
            pass

这篇博文更详细地解释了一般问题——尽管其中大部分内容并不真正适合这个特定问题。

于 2013-10-17T19:56:54.287 回答
1

您遇到的问题是您没有将事件循环代码嵌套在执行游戏逻辑的 while 循环中。这是您想要的一般结构:

while not end_program:
    while not end_game:
        handle_events()
        do_one_frame_of_game_logic()
    offer_another_game()

可能offer_another_game还需要使用自己的事件处理代码在自己的循环中运行。

实际上,您可能希望将要使用的逻辑封装到状态机系统中。你会有像PlayingGame,GameOver和那样的状态DoYouWantToPlayAgain,每个状态都会运行一段时间,然后切换到另一个状态。您的主循环将类似于:

state = StartState()
while state:
    state.handle_events()
    state.update()
    state.draw()
    state = state.next_state() # most of the time, the state will return itself
于 2013-10-18T08:45:37.000 回答