带摩擦力的运动算法

Movement algorithm with friction

比如我有一个水平跟随鼠标的对象,它的最小位置是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 // ???
}

问题与语言无关。

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

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

其中friction是计算你想要的"soft"函数的函数。一个简单的是:

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]区间外时完全停止。