Как правильно использовать easing-функцию для перемещения?
Подскажите, как изменить значение параметра, используя easing-функции. К примеру, для перемещения объекта. Перед началом перемещения я сохраняю такие данные:
Время анимации
Дистанция, которую нужно пройти
Расстояние одного шага (дистанция / время)
Количество шагов
Направление перемещения
Затем для линейного перемещения я в таймере перемещаю объект в нужном направлении на расстояние одного шага.
Для использования easing-функции я рассчитываю дополнительный параметр [0..1], который содержит процентное отношение пройденного пути к общей дистанции, и затем передаю этот параметр в функцию. Сама функция - InOutQuad - выглядит так:
x < 0.5 ? 2 * x * x : -1 + (4 - 2 * x) * x
В результате возвращаемое функцией значение я умножаю на длину одного шага, - думаю, что по логике это коэффициент, который изменяет размер шага так, чтобы общая пройденная дистанция из суммы всех шагов осталась неизменной. То есть, в начале пути объект двигается медленно, а в середине компенсирует это более быстрым перемещением.
Объект не доходит даже до середины пути и останавливается. Что я делаю не так?
Привожу свой код:
t = stepNum / animTime;
easing = t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
object.move(angle, stepDist * easing);
stepNum++;
Функция move() перемещает объект на заданное расстояние в заданном направлении. Я сам пока склоняюсь ко мнению, что такой метод перемещения конфликтует с идеей eeasing-функции, где, насколько я понял, перед началом анимации должно сохраняться начальное значение параметра, и потом каждый шаг анимации к нему должно прибавляться значение dist * easing. То есть, общая дистанция, умноженная на возвращенное значение.
Если так, подскажите, как можно подстроить эту функцию под такой метод перемещения.
Ответы (1 шт):
Приведённая формула - одна из реализаций S-образной кривой скорости, о которой я говорил прошлый вопрос. Формула показывает, на каком расстоянии будет находиться точка в зависимости от времени. А вот чтобы рассчитать шаг - нужна скорость, производная от этого перемещения. В данном случае профиль скорости треугольный - скорость линейно растёт до середины пути, потом линейно падает до нуля.
V = 4 * t в первой половине
Vh = 2 в середине
V = 2 - 2 * t во второй половине
Почему такие коэффициенты в easing функции и для скорости? Чтобы обеспечить площадь под кривой скорости (интеграл скорости по времени), равную единице (т.е. весь путь пройден за время t=1).
Имея готовую easing-функцию, Вы можете рассчитывать абсолютное положение точки в каждый момент времени, т.е она даёт не шаг, а положение. Если есть метод для абсолютного позиционирования - вычисляйте
object.moveToPoint(angle, fulldistance * easing);
Если только относительный сдвиг - то считайте шаг как разность между двумя easing-значениями для последовательных моментов времени.
lasteas = 0
...
easing = t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
object.move(angle, fulldistance * (easing - lasteas));
lasteas = easing
При необходимости можно опираться и на скорость для расчёта шага, но есть некоторые подводные камни - при ступенчатом движении суммарный результат может несколько отличаться от единицы.