08 марта 2017

Процедурные анимации - 2

(версия на английском)
Продолжаем...
Процедурная анимация - довольно интересная штука, и у меня куча идей, что можно показать и анимировать... но не хватает времени на банальный набор текста здесь, в блоге.
Сегодня добрался до клавиатуры, и мы делаем прыгающий мячик! (исходники здесь)


Если честно, то я давно хотел такое в свой арсенал. Было интересно, как можно простенько сделать сжатие при касании земли и растяжение в полете. Как оказалось - без математики не обойтись. Но мы, уверен, не боимся её после первого поста :)

Как прыгает мяч по-настоящему

Если коротко, то движение мяча можно показать на "параболе рожками вниз". Например, вот так:

красный, у=-(x-1)^2+1
 
"Оу, графики??" - удивитесь вы. А я отвечу - "да, иногда и графики бывают нужными, сегодня как раз такой случай" :) Но только не смотрите на функцию под графиком (я её привел просто так, чтобы всё было по-честному). Нам эта функция вообще не понадобится... в общем, продолжаем.
Итак, сначала объект двигается вверх, там немного повисел, притяжение планетой стало заметно, и тело устремилось вниз. Уверен, все помнят это из школы. Выглядит это приблизительно так:


Я использую такой метод часто, но не для цикличных движений. То есть кинуть что-то один раз - отлично, двигаемся по параболе. Но, если мне нужен отскакивающий много-много раз мячик (и особенно с дополнительным расплющиванием внизу) - то обычной параболой здесь не обойтись...

Как мы будем подбрасывать мяч

Где цикличность - там и синусы/косинусы. Представляю вашему вниманию абсолютное значение (в школах еще говорят "модуль") от синуса:

синий, y=abs(sin(x*pi/2))

Как мы видим, он ну прям очень похож на параболу. При этом цикличное движение выходит само по себе, и это отлично!



Сжатие внизу

Да, но обычное вверх-вниз движение выглядит очень деревянным и зажатым. Нам нужно больше экспрессии. Давайте думать, как это реализовать...
Сделаем следующий трюк. Смотрите, если немного поднять землю, то наш мячик будет какое-то время как будто под землей, вот так (на гиф я замедлил движение, чтобы лучше разглядеть):



Теперь, будем сжимать по вертикали спрайт так, чтобы его нижняя сторона всегда оставалась на земле, визуально не проваливаясь.


Ок, с масштабом по вертикали еще более-менее понятно, а как при этом растягивать мячик по горизонтали? Не вдаваясь в математику (идея в сохранении площади эллипса) скажу, что произведение масштабов оставляют прежним. То есть scale.x * scale.y = 1 всегда. Ок, попробуем:


Растяжение в полете

Вот здесь у меня был самый большой затык. Штука в том, что растяжение должно выглядеть естественным и при этом равномерным при движениях вверх и вниз. Проблема в том, что синус довольно быстро нарастает, а мне, наоборот, нужна пауза перед нарастанием. В таком случае я придумал применить степень от синуса, например, четвертую:


Снова масштаб по горизонтали меняем как scale.x = 1 / scale.y:


Ура! Немного математики и мячик ожил!

Полировка

И вроде всё хорошо. Но не до конца... Смотрите, как на последней гифке мячик очень мало времени проводит внизу сжимаясь-разжимаясь. (конечно, тут еще гиф съедает кадры) Хочется, чтобы он там чуточку задержался, давая взгляду возможность всё понять.
Для этого немного схитрим и изменим наш изначальный синус (для движения вверх-вниз). Возведем его в степень, и это позволит чуть быстрее падать, но при этом немного задерживаться внизу. Смотрим результат:


Итоговый код

Мне понравилось выкладывать исходники на WonderFL. Наглядно, просто, удобно.

Итого

Процедрные анимации, зачастую, несут много математики и требуют множества экспериментов. "В чем же тогда бонус всего этого барахла?" - спросите вы. Красота такого кода в легкой, быстрой и понятной настройке движений мячика. Можем изменить высоту прыжка, силу "расплющивания", время в нижней точке и многое другое... при этом общий стиль движения нашего мяча останется неизменным.
Вот пример двух констант (из исходников) и их влияния на движение:


На этом всё... процедурного всем счастья!

Сообщения, схожие по тематике:

0 коммент.:

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