要使用可变时间步长移动对象,我只需要执行:
ship.position += ship.velocity * deltaTime;
但是当我尝试这个时:
ship.velocity += ship.power * deltaTime;
我在不同的时间步骤得到不同的结果。我该如何解决这个问题?
修改
我正在模拟一个物体在一个轴上落地,并用一个固定的力(重力)作用于它。
答案 0 :(得分:8)
ship.position = ship.position + ship.velocity * deltaTime + 0.5 * ship.power * deltaTime ^ 2;
ship.velocity += ship.power * deltaTime;
http://www.ugrad.math.ubc.ca/coursedoc/math101/notes/applications/velocity.html
方程的速度部分是正确的,它们必须在每个时间步都更新。
这一切都假设你在belisarius指出的deltaTime上有恒定的功率(加速度)。
答案 1 :(得分:4)
你在做什么(数学上)是评估积分。在第一种情况下,线性近似是精确的,因为你有线性关系。
在第二种情况下,您至少有一个抛物线,因此您的结果只是近似值。通过使用较小的deltaTime或使用实数积分方程(如果可用),可以获得更好的结果。
修改
只要ship.power保持不变,并且每一步都重新计算ship.velocity,Brian的回答是正确的。它确实是恒定加速运动的积分方程式。答案 2 :(得分:1)
这是尝试数字整合的固有问题。会有错误。降低delta将为您提供更准确的结果,但需要更多计算。如果你的幂函数是可积的,你可以试试。
答案 3 :(得分:1)
您的模拟在数值上解决单个质点的运动方程。您正在使用的时间离散称为"Euler method",并且可以表明它不会保留能量(正如确切的解决方案在某种程度上所做的那样)。求解运动方程的一种更好但更简单的方法是"leapfrog integration"。
答案 4 :(得分:0)
您可以使用Verlet integration来计算物体的位置和速度。加速度可以从a = m * F计算,其中m是质量,F是力。这是最简单的算法之一
答案 5 :(得分:0)
在您的代码中,您使用setInterval(moveBoxes,20)更新框,然后使用(new Date())。getTime())来计算deltaT。这有点多余,因为您可以使用数字20直接计算deltaT。
最好编写代码,以便在每个时间步骤中为deltaT使用相同的值。 (换句话说,deltaT不应该依赖于(new Date())的值.getTime()))。这样,您的代码就变得可以重现,并且您更容易编写单元测试。
让我们看一下浏览器在短时间内可用的CPU时间较少的情况。在这种情况下,您希望避免对动态的长期影响。缺少CPU时间就是你希望浏览器返回一个不受CPU时间短缺影响的状态。您可以通过在每个时间步长中使用相同的deltaT值来实现此目的。
顺便说一下。我认为以下代码if(box.x < 0) {
box.x = 0;
box.vx *= -1;
}
可以替换为
if(box.x < 0) {
box.x *= -1 ;
box.vx *= -1;
}
祝你好运项目 - 请在下次问你问题的第一个版本时加入代码示例: - )