我目前正处于使用pygame为学校项目制作经典2D平台游戏的早期阶段,当我遇到这个相当奇怪的问题时,我正在试验跳跃机制。尽管我已经考虑了更新之间的时间增量,但当帧之间的时间增加时,跳跃长度和高度都会变短。
在这里,我让 Player 对象的 3 个实例在屏幕上跳转,以 700 像素/秒的恒定速度和 700 像素/秒的初始向上速度向右移动。他们每个人都有人为增加的最小delta_time分别为0.001s,0.017s和0.1s。
这就是在 Player 对象的更新函数中计算新速度和位置矢量的方式,该函数每帧调用一次(delta_time从主更新循环传入(:
self.speed.y += 1000.0 * delta_time
self.position += self.speed * delta_time
这就是在主更新循环的每个周期结束时计算delta_time的方式(第一帧的值为零(:
delta_time = time.time() - pre_time
pre_time = time.time()
if delta_time < min_delta_time:
time.sleep(min_delta_time - delta_time)
delta_time += time.time() - pre_time
pre_time = time.time()
min_delta_time表示帧更新之间的最短时间。
经过多次尝试解决此问题,我很确定缺陷在于更新速度的行,但即使仔细检查了数学,我仍然无法弄清楚问题是什么。起初我认为可能是delta_time不精确,但如果是这样的话,水平速度也会受到影响,小径仍然会排成一排。
那么我可以改变任何东西以使跳跃/重力更加一致吗?
与其说是编码中的错误,不如说是模型中的逻辑错误:通过将加速建模为在更新点即时发生而不是在整个时间跨度内连续发生,引入了不准确性,更新越稀疏,误差就越大。
为了说明这一点,考虑一个物体从停止处以 1m/s^2 的速度加速。如果我们以 1 秒的间隔进行上述建模,则在 6 秒后,我们的模型会将物体置于 21m 处。以 2 秒的间隔重复,我们将它放在 24m,3 秒间隔将把它放在 27m。但是,实际位置应该是18m。
解决方案是考虑模拟时间跨度内的平均速度,而不是采样点的瞬时速度。换句话说,与其计算整个跨度的加速度值,然后将结果用作整个跨度的速度,不如将跨度的加速度相加一半,使用该速度计算在该跨度中行进的距离,然后添加剩余的一半加速度。
因此,您的更新逻辑将变为:
self.speed.y += 500.0 * delta_time
self.position += self.speed * delta_time
self.speed.y += 500.0 * delta_time