摩擦运动算法

时间:2019-04-15 06:29:38

标签: algorithm language-agnostic physics spring-annotations

例如,我有一个水平跟随鼠标的对象,其最小位置为100,最大位置为200。

在此范围内,它线性跟随鼠标,这意味着1单位鼠标位置等于1单位对象位置。

现在,如果鼠标超出范围(低于100,或高于200),我希望它开始施加摩擦,因此对象在距离范围更远的地方会优雅地停止,例如:

Mouse position  | Object position
200               200
220               205
240               209
260               212
280               215
300               217
320               218
340               219
360               220
380               220
400               220
...

我设法在鼠标移动处理程序中像这样实现它:

if (mousePosition > 200 || mousePosition < 100) {
  delta = mousePosition - objectPosition;
  objectPosition += delta * 0.25; // 0.25 if friction factor
}

但是有更好的方法吗?如何在鼠标移动处理程序之外实现功能:

getObjectPosition(mousePosition) {
  return // ???
}

这个问题与语言无关。

1 个答案:

答案 0 :(得分:2)

您可以将对象位置计算为鼠标位置的分段函数:

getObjectPosition(mousePosition) {
    if(mousePosition < 100)
        return 100 - friction(100 - mousePosition);
    if(mousePosition > 200)
        return 200 + friction(mousePosition - 200);
    return mousePosition;
}

其中friction是用于计算所需的“软”函数的函数。一个简单的例子是:

friction(x) {
    return 0.25*x;
}

,当超出[100,200]范围时,它将使对象速度降低0.25。您的函数似乎接近某种渐近线。您可以使用例如二次方来实现它:

friction(x) {
    M = 160;
    x = min(x, M);
    return x*(1 - x/(2*M));
}

在此对象将逐渐变慢,并在鼠标位于[-60,360]间隔之外时完全停止。