我正在制作一个总是面向鼠标位置且平滑过渡的物体 - 加速和减速。
对于靠近鼠标的减速,这是一个简单的等式:
rotation += deltaRotation / speed
为了加速,会有更多的代码(但它会在目标旋转周围摆动,因为没有摩擦或阻尼)
var deltaRotation = rotation - targetRotation;
if (Math.abs(deltaRotation) < EPSILON) { //Stop motion near 0
return;
}
var direction = deltaRotation != 0 ? deltaRotation / Math.abs(deltaRotation) : 0;
dv += ACCELERATION * direction * dt;
dv = FMath.clamp(dv, -MAX_SPEED, MAX_SPEED);
rotation += dv * deltaRotation;
如何合并这两种算法,这样旋转会慢慢开始并慢慢达到目标旋转?
答案 0 :(得分:1)
在物理世界中,加速度与施加的力成比例。模拟在给定时间步长施加的力的一种方法是使其与您需要移动的距离成比例,减去一些阻尼力。阻尼力(如摩擦力或风阻力)与当前速度的方向相反并且与当前速度成比例。阻尼力有效地限制了最高速度,并在直接力下降时提供了良好的减速度。
考虑一个线性系统。让我们说xCursor
是光标的位置,xMonster
是追逐光标的东西的位置。让我们使用dxMonster
来获得怪物的速度。
首先我们需要知道我们有多远,因为我们想根据那个加速怪物。
float delta = xCursor - xMonster;
force
是净力量。它包括一个直接的力,使怪物朝着光标加速,一个阻尼力抵抗怪物的当前速度。
float force = A*delta - B*dxMonster;
您可以使用常量来查看最佳效果。你可能想要A < B
。在我的测试计划中,我使用了A = 0.1
和B = 0.5
。
由于加速度与力成正比,我们可以直接将其加到力度上。请注意,我们不再需要钳制速度,因为阻尼力将使其不会变得太大。然后使用速度来更新位置。 (在更好的模拟中,您可以使用像Runge-Kutta这样的东西来更好地进行积分,但只需在每个时间步骤添加一个简单的动画就可以了。)
dxMonster += force;
xMonster += dxMonster;
每个时间步重复一次。我省略了dt
s,因为我的帧速率足够稳定,并不重要。
你的问题是关于旋转而不是线性运动,但这完全是类似的。从物理角度来说,它只是角速度和扭矩而不是线速度和力。