pygame.time.wait()使窗口freez

时间:2013-09-09 11:43:24

标签: python pygame

我有一个简单的动画来处理我绘制矩形的位置,当我点击表面时,矩形向左滑动并等待2秒,然后向右滑动重绘它,但如果我减少或移动窗口试一试窗口在等待时刻冻结。

以下是代码:

import sys, pygame
from pygame.locals import *

pygame.init()

FPS       = 30
BGCOLOR   = (255, 255, 255)
RECTCOLOR = (10, 0, 199)
DS        = pygame.display.set_mode( (200,200) )
CLOCK     = pygame.time.Clock()
pygame.display.set_caption('Demo')

def main():
    DS.fill(BGCOLOR)
    pygame.draw.rect(DS, RECTCOLOR, (50, 50, 100, 100))
    pygame.display.update()

    while 1:
        ev = pygame.event.wait()
        if ev.type == QUIT:
            pygame.quit()
            sys.exit()
        elif ev.type == MOUSEBUTTONUP:
            animation()


def animation():
    pygame.event.set_blocked(MOUSEBUTTONUP)
    for x in range(10, 101, 10):
        pygame.draw.rect(DS, BGCOLOR, (150 - x,50,x,100))
        pygame.display.update()
        CLOCK.tick(FPS)
    pygame.time.wait(2000) # 2 seconds
    for x in range(10, 101, 10):
        pygame.draw.rect(DS, RECTCOLOR, (50,50,x,100))
        pygame.display.update()
        CLOCK.tick(FPS)
    pygame.event.set_allowed(MOUSEBUTTONUP)

if __name__ == '__main__':
    main()

为什么我们会出现这种行为?也许系统不会在第二个for循环中的暂停时刻和刻度之间同步

PS:我在Windows 7上,对不起我的英语,这不是我的母语

3 个答案:

答案 0 :(得分:1)

两件事:

当您运行这样的循环时:

for x in range(10, 101, 10):
        pygame.draw.rect(DS, BGCOLOR, (150 - x,50,x,100))
        pygame.display.update()

你绘制动画,但是pygame没有机会处理它从你的操作系统获得的消息。为避免这种情况,您应该在循环内调用pygame.event.pump()pygame.event.get()

来自docs

  

<强> pygame.event.pump()

     

对于游戏的每一帧,您需要对事件队列进行某种调用。这可确保您的程序可以在内部与操作系统的其余部分进行交互。如果您没有在游戏中使用其他事件函数,则应调用pygame.event.pump()以允许pygame处理内部操作。

     

如果程序通过其他pygame.event函数一致地处理队列中的事件,则不需要此函数。

     

必须在事件队列内部处理重要事项。主窗口可能需要重新绘制或响应系统。如果您未能长时间调用事件队列,系统可能会决定您的程序已被锁定。

此外,在移动窗户时,您的游戏将会冻结。这是SDL的一个已知限制(记住pygame只是SDL的一个薄包装)并且由Windows消息循环引起:当你移动窗口或调整窗口大小时,windows使用模态循环,这将阻止游戏运行的线程

答案 1 :(得分:1)

我建议您只使用一个循环并使用变量或用户事件来跟踪游戏状态。

示例:

game_state = 0

def main():
    global game_state
    rectangle_ticks = 0

    while 1:
        events = pygame.event.get()   # Get all pending events

        for ev in events:
            # Process events
            if ev.type == QUIT:
                pygame.quit()
                sys.exit()

            elif ev.type == MOUSEBUTTONUP:
                game_state = 1
                pygame.time.set_timer(pygame.time.set_timer(pygame.USEREVENT + 1, 1000)

            elif ev.type == pygame.USEREVENT + 1:
                pygame.time.set_timer(pygame.time.set_timer(pygame.USEREVENT + 1, 0)
                game_state = 2

        # Clear screen
        DS.fill(BGCOLOR)

        # Draw game state
        pygame.draw.rect(DS, RECTCOLOR, (50, 50, 100, 100))
        animation()

        # Update screen
        pygame.display.flip()

        CLOCK.tick(FPS)

def animation():
    if game_state == 1:
        for x in range(10, 101, 10):
            pygame.draw.rect(DS, BGCOLOR, (150 - x,50,x,100))

    if game_state == 2:
        for x in range(10, 101, 10):
            pygame.draw.rect(DS, RECTCOLOR, (50,50,x,100))

在每个刻度中绘制整个屏幕可能看起来很奇怪,但这是在pygame中工作的常用方法,以便摆脱不想继续绘制的旧对象。

答案 2 :(得分:1)

pygame.time.wait(1000) # 2 seconds

这会导致代码暂停2秒。所以你不会在2秒之后得到任何事件。

您需要将get_ticks()用于动画或计时器。