Алгоритм движения с трением - PullRequest
1 голос
/ 15 апреля 2019

Например, у меня есть объект, который следует за мышью по горизонтали, его минимальная позиция равна 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 Ответ

2 голосов
/ 15 апреля 2019

Вы можете рассчитать положение объекта как кусочную функцию положения мыши:

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;
}

, что уменьшит скорость объекта на 0,25, когда она выходит за пределы [100, 200]. Ваша функция, кажется, приближается к некоторой асимптоте. Вы можете достичь этого, например, с помощью квадратичного:

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

Здесь объект будет постепенно замедляться и полностью останавливаться, когда мышь находится за пределами интервала [-60, 360].

...