21 апреля 2017

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

(English version)
"Мощь синуса" - так я решил назвать сегодняшние анимации. Да, функция синуса - очень крутая :) Если что: косинус - это тот же синус, только смещённый немного. Вообще не знаю, зачем ввели эту вторую функцию под названием "косинус" - возможно, просто для сокращения некоторых математических записей. А так - вполне достаточно было бы одной из них...
Что-то я отвлёкся! Сегодня делаем такие анимашки:

Плавное движение "туда-сюда"

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

y = y0 + 10 * sin(t * 3);

10 - это насколько сильным будет колебание по амплитуде
3 - скорость колебаний
t - время (меняется каждый кадр)
Результат:




Маятник

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

rotation = 10 * sin(t * 3)

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

for(var i: int = 0; i < 360*3; i++)
lineTo(R*i/360 * Math.cos(i/360 * Math.PI*2), R*i/360 * Math.sin(i/360 * Math.PI*2) );

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




Дыхание

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

scaleX = 1.1 + 0.15 * Math.sin( t * 3 );
scaleY = 1 + 0.1 * Math.sin( t * 3 - 0.7);

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

 time += 1/fps; 
 t += (Math.sin(time * Math.PI) + 1) / fps / 2;

В этом случае наш объект будет чуточку замирать в крайних точках (каждые 1/Math.PI секунд). Результат:




Орбита

Вообще, синус пришёл из окружности. Нужна была функция, описывающая движение точки по этой самой окружности. Назвали "синус", дали математическое описание и вперёд... Теперь мы пользуемся тем, что движение по окружности - само по себе периодическое, цикличное. Все предыдущие примеры как раз и использовали это свойство.
Теперь же мы воспользуемся коренной функцией синуса - окружностью! Чуть сдавим её, чтобы получить эллипс и запишем вот такую систему для движения точки:

x = 65 * Math.cos(time * 3);
y = 25 * Math.sin(time * 3);

Из-за того, что значения полуосей (65 и 25) сильно различны, то у нас как раз и выходит эллипс. Сделайте их одинаковыми - и получится окружность :)
А вот и наша луна ( вроде 60 фпс, а как-то дёргается гиф):


Исходный код

Выложил на DropBox.
Качаем, смотрим, комментируем!

Если есть какие идеи, что можно рассказать в подобных постах-туторах - кидайте ссылки на видео или гифки, где это сделано, а я попробую реализовать кодом и сделать в привычном формате "процедурные анимации".
Всем всего хорошего!

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

0 коммент.:

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