我正在使用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。您将给予的任何帮助将不胜感激!
答案 0 :(得分:0)
我找到了一种消除我遇到的单帧延迟的方法,虽然我仍无法解释为什么pygame.display.update()
等待时钟延迟来更新屏幕。我想我会在这里发布我的解决方案以防其他人有同样的问题。
我注意到显示将在pygame.event.get()
运行后更新,因此我设置循环以更快的帧速率检查事件。我仍然只想运行我的游戏逻辑并以较低的频率更新屏幕,所以我只计算循环执行的次数。请注意以下新示例中的变量frequency
,FPS
和skip_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)