我正试图了解这些整合方法,但我一直很困惑。
以下是代码:
public void update_euler(float timeDelta){
vPos.y += vVelocity.y * timeDelta;
vVelocity.y += gravity.y * timeDelta;
}
public void update_nsv(float timeDelta){
vVelocity.y += gravity.y*timeDelta;
vPos.y += vVelocity.y * timeDelta;
}
public void onDrawFrame(GL10 gl) {
currentTime = System.currentTimeMillis();
float timeDelta = currentTime - startTime;
startTime = currentTime;
timeDelta *= 1.0f/1000;;
// update_RK4(timeDelta);
// update_nsv(timeDelta);
// update_euler(timeDelta);
// update_velocity_verlet(timeDelta);
}
首先,我只是想确保我有这些权利。
我正在模拟一个完全弹性的球弹跳,所以在反弹时我只是反转速度。
欧拉方法,球在每次弹跳时反弹得更高。这是由于我的代码中的错误,还是由于该方法的无效性。我已经读到,随着欧拉积分,你会随着时间的推移而失去能量。好吧,我正在获得它,我不知道为什么。
nsv方法:我不太明白这与Eular方法有什么不同,但无论如何球在每次反弹时都会反弹。它正在失去能量,我已经读过并不意味着用nsv方法发生。为什么我会失去能量?
(速度verlet和RK4方法正如我所期望的那样工作)。
我得到的印象是我缺乏关于这个主题的基本信息,但我不知道是什么。
我确实意识到我的时间步缺失,并且使用静态时间步长更新它以运行物理将阻止我失去/获得能量,但我试图了解发生了什么。
任何帮助都将不胜感激。
答案 0 :(得分:2)
要为@ Beta的答案添加另一个选项,如果您平均这两种方法,您的错误应该会消失(除了处理实际反弹的问题)。
public void update_avg(float timeDelta){
vVelocity.y += gravity.y*timeDelta/2;
vPos.y += vVelocity.y * timeDelta;
vVelocity.y += gravity.y*timeDelta/2;
}
我在这里做的是将速度更新为区间内的平均速度,然后根据该速度更新位置,然后将速度更新为间隔结束时的速度。
如果您想要建模更复杂的场景,请考虑使用Runge-Kutta Method来解决y' = f(x, y)
形式的微分方程。 (请注意,这里y
可以是一组不同的变量。所以在你的情况下你有d(position, velocity)/dt = (velocity, -gravity)
。我给你的代码与二阶版本相同那种方法。
答案 1 :(得分:1)
在现实生活中,球向上移动并减速,到达顶点(远地点),其速度为零,持续一秒钟,然后向下移动并加速。在任何时间间隔内,它都在与势能(高)交换动能(快速)。
在欧拉方法中,它以恒定速度移动一段时间,然后在间隔结束时突然改变其速度。因此,在向上的旅程中,它会以高速上升,然后减速,获得更多的高度。在向下的腿上,它缓慢地向下爬行,失去一点高度,然后加速。
在nsv方法中,情况正好相反:在上升的过程中,它“速度太快”会失去速度并且不会变得非常高,在向下的路上它会匆匆赶到地面而不会增加很多速度。
这两种方法的限制相同,因为timeDelta
为零。 (如果这句话毫无意义,不要冒汗,那只是微积分。)如果你让timeDelta
变小,效果就会消失。或者你可以使用能量作为你的主要变量,而不是{position,velocity},但数学会更复杂。
答案 2 :(得分:0)
集成将人工阻尼引入系统。我相信你可以通过对集成方案进行傅立叶分析来确定很多,但我必须更新我对内容的了解。