【发布时间】:2016-02-25 19:16:37
【问题描述】:
我用 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()
以该帧速率输出的 sn-p:
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 时输出的 sn-p(而不是仅当它 > 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,而此问题不太明显),所以我的环境可能有问题.我确实(有点)在第二台机器上重现了这个问题(如上所述),所以我宁愿不要忽视这个问题,希望最终用户不会遇到它......
【问题讨论】:
-
我没有直接的答案,但这些是解决时间步长问题的好资源:gafferongames.com/game-physics/fix-your-timestep,gamedev.stackexchange.com/questions/1589/…
-
@monkey 感谢您的链接。使用 dt 可以防止此问题影响游戏/模拟,但问题本身仍未解决。我想我只能希望用户不会注意到口吃之类的。
-
由于您使用的是pygame,您可以从
pygame.time.get_ticks()pygame.org/docs/ref/time.html#pygame.time.get_ticks获取当前经过的时间 -
我在 python 2.7.2 pygame 1.9.1release,windows 7 上测试了你的代码,没问题,time_spent 总是在 0.0004~5 左右
-
试试 pygame.display.flip()