2

我有一个简单的动画来处理绘制矩形的位置,当我单击表面时,矩形向左滑动并等待 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 上,抱歉我的英语不是我的母语

4

3 回答 3

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()or 。pygame.event.get()

文档

pygame.event.pump()

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

如果您的程序通过其他 pygame.event 函数持续处理队列上的事件,则不需要此函数。

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

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

于 2013-09-09T12:18:51.830 回答
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 中工作的常用方法,以便摆脱您不想继续绘制的旧对象。

于 2013-09-09T13:41:42.120 回答
1
pygame.time.wait(1000) # 2 seconds

这会导致代码在此处暂停 2 整秒。因此,直到 2 秒后,您才会收到任何事件。

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

于 2013-09-09T19:42:35.427 回答