我用 Pygame 做了一个简单的程序,它基本上是一个滚动的背景,并注意到周期性的滞后峰值。弄乱代码很长时间后,我发现对 pygame.display.update() 的调用有时会花费更长的时间来执行。
为了真正简化并复制问题,我编写了以下代码:
import pygame
import sys
import time
FRAME_RATE = 30
# don't mind the screen and time_passed variables; they aren't used in this script
def run_game():
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((500, 500))
prev_spike = 0
time_passed = 0
while 1:
start = time.clock()
pygame.display.update()
timenow = time.clock()
time_spent = timenow - start
if time_spent > 0.01:
print time_spent
if prev_spike:
print "Last spike was: {} seconds ago".format(timenow - prev_spike)
prev_spike = timenow
time_passed = clock.tick(FRAME_RATE)
if __name__ == "__main__":
run_game()
该帧速率的输出片段:
0.0258948412828
Last spike was: 1.01579813191 seconds ago
0.0186809297657
Last spike was: 0.982841934526 seconds ago
0.0225958783907
Last spike was: 2.01697784257 seconds ago
0.0145269648427
Last spike was: 1.01603407404 seconds ago
0.0186094554386
Last spike was: 2.01713885195 seconds ago
0.0283046020628
Last spike was: 1.03270104172 seconds ago
0.0223322687757
Last spike was: 1.01709735072 seconds ago
0.0152536205013
Last spike was: 1.01601639759 seconds ago
我真的不知道发生了什么,并且真的很想得到一些见解。
更多细节:
在每次循环迭代中打印 time_spent 时的输出片段(而不是仅当它 > 0.01 时):
0.000204431946257
0.000242090462673
0.000207890381438
0.000272447838151
0.000230178074828
0.0357667523718 <-- update taking two orders of magnitude longer than normal
0.000293582719813
0.000343153624075
0.000287818661178
0.000249391603611
当以 60 FPS 运行时,每个尖峰之间的间隔几乎总是 1 秒,很少是 2 秒(尖峰将持续大约两倍的时间)。在较低的帧速率下,尖峰之间的间隔将开始变化更大,但始终接近整数值。
我尝试在另一台计算机上运行脚本,但问题没有被复制;pygame.display.update() 的执行时间相当快且一致。然而,当我在那台机器上运行我的原始程序时,一秒间隔的滞后峰值仍然存在(我可能会寻找其他机器来测试......)
我测试的两台机器都运行 Windows 7。
编辑:
我抓了一些在 Pygame 网站上托管的随机游戏,我得到了类似的行为——调用pygame.display.update
(或flip
)周期性地需要 10 到 40 毫秒,而它们通常需要不到 2 毫秒。
似乎没有其他人遇到这个问题(或者至少抱怨过。这可能是因为大多数游戏的运行速度低于 30 FPS,而这个问题不太明显),所以我的环境可能有问题。我确实(有点)在第二台机器上重现了这个问题(如上所述),所以我宁愿不要忽视这个问题,希望最终用户不会遇到它......