Pygame:display.update()直到时钟延迟后才更新

时间:2018-05-07 16:53:34

标签: python-3.x pygame

我正在使用pygame' s time.Clock以较低的FPS运行我的游戏,我注意到我的输入似乎需要一个额外的帧才能生效。我做了一些调试并意识到它与pygame.event.get()不是问题,而是pygame.display.update()。我写了一个简单的程序来演示这个问题:(程序说明在代码片段下面)

import pygame, sys
from pygame.locals import *

pygame.init()
screen = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
colour = 1
key_press = False

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == KEYDOWN:
            screen.fill((0,255,0))
            key_press = True
            print("A key was pressed.")

    if not key_press:
        screen.fill((colour*255, colour*255, colour*255))
        colour = not colour
    else:
        key_press = False

    pygame.display.update()
    clock.tick(0.5)

程序每隔两秒闪烁一次黑白屏幕,每按一次键,屏幕就会变为绿色,"A key was pressed"将打印到控制台。但是,当我运行它时,文本将在正确的时间打印,但屏幕在下一帧之前不会变为绿色。这让我相信pygame.display.update()在调用函数时没有更新屏幕。

问题似乎是在调用pygame.display.update()后立即出现延迟。如果更改时钟的FPS,问题仍然存在。如果您延迟time.wait()pygame.time.delay()而不是Clock.tick(),也会发生这种情况。

我注意到的另一个有趣的事情是,如果你反转我的示例(pygame.display.update()clock.tick(0.5))中最后两行代码的顺序,你可能会想到屏幕按下一个键而不是一个键后,将改变两个时钟周期。但是,如果我这样做,我会获得与其他顺序相同的效果。

我不确定这是不是一个错误,或者我是否错过了一些微妙的事情。我正在运行Python 3.6.2并在macOS上使用Pygame v1.9.3。您将给予的任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:0)

我找到了一种消除我遇到的单帧延迟的方法,虽然我仍无法解释为什么pygame.display.update()等待时钟延迟来更新屏幕。我想我会在这里发布我的解决方案以防其他人有同样的问题。

我注意到显示将在pygame.event.get()运行后更新,因此我设置循环以更快的帧速率检查事件。我仍然只想运行我的游戏逻辑并以较低的频率更新屏幕,所以我只计算循环执行的次数。请注意以下新示例中的变量frequencyFPSskip_frames

import pygame, sys
from pygame.locals import *

pygame.init()
screen = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
colour = 1
key_press = False
frequency = 0.5 # How often the game logic is run
FPS = 30 # How often the user input is checked
skip_frames = FPS/frequency
count_frames = 0

while True:
    # *** Check for user input every loop ***
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == KEYDOWN:
            key_press = True

    # *** Only run game logic at given frequency ***
    if count_frames >= skip_frames:
        count_frames -= skip_frames

        if key_press:
            screen.fill((0,255,0))
            print("A key was pressed.")
            key_press = False
        else:
            screen.fill((colour*255, colour*255, colour*255))
            colour = not colour

        pygame.display.update()

    count_frames += 1
    clock.tick(FPS)

这是一个解决方法,但它给出了我想要的结果。屏幕将以给定频率闪烁,按任意键后,屏幕将变为绿色。如果有人能弄清楚为什么pygame.display.update()等待时钟延迟来实际更新屏幕,我会非常有兴趣知道。

答案 1 :(得分:0)

pygame.time.Clock.tick source调用SDL_Delay,让程序在给定时间内休眠。

通过将0.5作为帧速率传递给clock.tick,您可以告诉pygame减慢速度,这样每秒只处理半帧。这实际上意味着游戏只会每两秒钟更新一次,并且在其余时间内不会响应。

如果要在pygame中实现计时器,请使用solutions here之一(pygame.time.get_ticks,set_timer或使用增量时间)。

答案 2 :(得分:-1)

我能够通过在pygame.display.update()调用和之间调用pygame.event.pump()(不会清除事件队列,因此不会丢失事件处理)来解决此故障。 clock.tick(FPS)调用。基本上,我的主要游戏循环以:

pygame.display.update()
pygame.event.pump()
clock_object.tick(FPS_CONSTANT)