添加额外的循环会导致无响应

时间:2013-10-17 19:40:21

标签: python performance loops pygame

我正在使用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()

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

2 个答案:

答案 0 :(得分:3)

问题是,如果你没有运行事件循环,游戏就无法响应或做任何事情。在另一个循环中,您没有运行事件循环。

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

所以,你必须将你的循环分成几步,并且每次通过事件循环只做一步(或几步)。

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

或者,将其更改为if将其移至for内,因此现在每个事件只运行一次,而不是每个事件循环迭代运行一次。

第三种方法是将整个事物分解为一个函数并将其设置为空闲或计时器函数,该函数在事件循环空闲时运行,或者每帧运行一次,或者每20ms运行一次,或等等。

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

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

This blog post更详细地解释了一般性问题 - 尽管大多数问题并不适合这个特定问题。

答案 1 :(得分:1)

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

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

offer_another_game也可能需要在自己的循环中运行,并有自己的事件处理代码。

实际上,您可能希望将要使用的逻辑封装到状态机系统中。您有PlayingGameGameOverDoYouWantToPlayAgain等状态,每个状态都会运行一段时间,然后交给其他状态。你的主循环就像是:

state = StartState()
while state:
    state.handle_events()
    state.update()
    state.draw()
    state = state.next_state() # most of the time, the state will return itself