Страницы

Поиск по вопросам

суббота, 9 марта 2019 г.

Подсчет шагов разных размеров - для более натуральной анимации Canvas

Здесь на русском StackOverflow я получил очень хороший совет и смог добавить анимацию фишек в буквенную игру для Android.
Когда пользователь выбирает в меню "Вернуть буквы" и буква "A" должна прилететь в позицию внизу экрана, показанную красной стрелкой:

Нынешний алгоритм работает так:
Текущие координаты фишки: mRect.top и mRect.left Конечные координаты фишки: mTarget.x и mTarget.y Пока на нем есть движущиеся фишки, экран мобильного приложения рисуется заново (для этого снова и снова вызывается postInvalidate(30)).
Когда нужно анимированно переместить фишку, я вызываю следующий метод, который делит предстоящий путь на 8 одинаковых шагов:
public void startAnimatedMove(float x, float y) { mTarget.x = x; mTarget.y = y; steps = 8; mStepX = (mTarget.x - mRect.left) / steps; mStepY = (mTarget.y - mRect.top) / steps; }
Каждый раз, по истечении 30 миллисекунд, вызывается метод, сдвигающий фишку в нужном направлении (причем последний шаг у меня особый - он помещает фишку точно на mTarget.x и mTarget.y - чтобы избежать ошибки округления):
private void nextStep() { if (--steps == 0) moveTo(mTarget.x, mTarget.y); else moveTo(mRect.left + mStepX, mRect.top + mStepY); }
Этот алгоритм работает хорошо (и дает возможность анимировать фишки прямо из главного thread-а приложения), но так как шаги mStepX и mStepY одинаковые, фишка движется неестественно.
Вопрос:
Как бы сделать шаги неодинаковыми? Они дожны быть большими в середине пути - и маленькими в начале и конце (см. зеленый график наверху справа). Тогда фишка будет медленно начинать и заканчивать движение - так называемый "easying in out".
То есть нужна функция (с использованием x*x или Math.sin()?) для каждой оси, которая получала бы как input номер текушего шага, а выдавала как output дистанцию в пикселях вдоль оси икс или игрек:
private void nextStep() { if (--steps == 0) moveTo(mTarget.x, mTarget.y); else moveTo(mRect.left + calcStepX(steps), mRect.top + calcStepY(steps)); }
Обновление:
Нашел интересный сайт про Easing Equations by Robert Penner, но пока не разобрался, как применить их к своему программному коду - особенно как рассчитать шаги, чтобы их сумма попала в точку назначения...


Ответ

как расчитать шаги, чтобы их сумма попала в точку назначения
Все формулы на упомянутом сайте опираются на 4 параметра: t, b, c, d
t – текущее время (или номер кадра), b – начальное значение, c – (конечное значение - начальное значение), d – общая длительность анимации.
Чтобы за 8 кадров некий параметр, напр., Y, изменился от 162 до 288, вы в понравившуюся формулу, напр., в экспонениальный out
return c * ( -Math.pow( 2, -10 * t/d ) + 1 ) + b;
подставляете b,c вашей анимации, d=7, а t=просчитываемый кадр (0..7) и получаете на выходе значение вашего параметра для этого кадра.

Комментариев нет:

Отправить комментарий