В прошлый раз был синус... сегодня продолжаем с чем-то похожим. Круги и окружности! Гипнотические анимашки, простые формулы, сплошной код и математика - в общем всё то, что называется "процедурной анимацией". Готовьте печеньки, чай и уютный диван... будем делать красоту!
Например, вот такую:
Отвлечёмся от общих анимаций и приёмов, и попробуем сделать что-то сугубо специфическое, но при этом всё равно прикольное. Ведь зачастую сами задачи возникают как "сделать вот такую анимацию". И изначально кажется, что другого применения не будет, что сама анимация очень специфическая. На просторах интернета я видел разные забавные гифки, и вот теперь решил их повторить в качестве жертвы процедурной анимации!
Непонятная цепь
Начнём вот с такой ерундовины:Сначала кажется, что движение кружков хаотично, но при этом немного красивое. На самом деле за этим непонятным движением кроется обычная окружность. Дорисую небольшие вспомогательные круговые элементы, и всё встанет на свои места:
При этом поворот каждой окружности записывается одной строкой:
circles[i].rotation = (Math.cos(timeValue - Math.PI) + 1) * 90;
Круто? А-то!
Пробежимся в цикле по всем окружностям и получим итоговое движение!
Подчеркну: одна строчка кода! одна формула! Ну разве не прелесть? Прелес-с-с-ть...
Пробежимся в цикле по всем окружностям и получим итоговое движение!
Подчеркну: одна строчка кода! одна формула! Ну разве не прелесть? Прелес-с-с-ть...
Концентрические окружности
Продолжаем нашу вакханалию... еще одна непонятная анимированная штуковина, которая может радовать глаз бесконечно:
Стоит отметить, что здесь есть не только движение эллипсов вниз-вверх, но и слабо заметное появление новых эллипсов снизу, и пропадание "в никуда" сверху. Вдобавок нижние эллипсы сильнее развёрнуты для достижения 3д-эффекта. Присмотритесь!
Итак, базовое расположение эллипсов - это обычный косинус :) Только у каждого эллипса он смещён по фазе вот так:
_y = cos( i / count * Math.PI ) * 90;
При этом значение каждого радиуса тоже описывается простенькой формулой:
_r = sin( i / count * Math.PI );
Чтобы сделать анимацию, сделаем вот такую "добавку": всего лишь один косинус, с параметром "время" внутри:
20 * cos(i / count * Math.PI * 1.5 + time * 2 * Math.PI / 2);
А пропадание/добавление - это простое изменение размеров самих эллипсов. Изменим функцию для angle (которая напрямую используется в _r) и получим необходимый эффект:
angle = (i + time / 2) / count * Math.PI;
Ну и напоследок я еще решил сделать небольшой 3d-эффект, при котором нижние эллипсы чуточку развёрнуты к зрителю. Сделать это можно так: верхние эллипсы рисуются более вытянутыми, а нижние - сплюснутыми. Такая добавка (perspective) участвует только при отрисовке в качестве параметра height эллипса.
В итоге все формулы для отрисовки нашей анимации выглядят вот так:
angle = (i + time / 2) / count * Math.PI;
perspective = (1 - angle / Math.PI) * b / 3;
_y = Math.cos( angle ) * 90 + 20 * Math.cos(angle * 1.5 + time * 2 * Math.PI / 2);
_r = Math.sin( angle );
graphics.drawEllipse(-_r * a/2,
-_r * b/2 + _y,
_r * a,
_r * (b + perspective ));
Чего-то много математики вышло, сорри...)))
Здесь у нас куча кругов, которые сначала сходятся в один круг, а потом разлетаются в виде цветка. В итоге центры кругов всё время лежат на окружности, радиус которой постепенно увеличивается. Такие дела... математика выглядит для x и y центра каждого круга вот так:
Radius = r * (Math.cos(time) + 1) / 2;
circles[i].x = Math.cos(i / (count) * Math.PI * 2 + time * 1 ) * Radius;
circles[i].y = Math.sin(i / (count) * Math.PI * 2 + time * 1 ) * Radius;
Как всегда тут еще есть заморочка с небольшими паузами в начале и конце каждого движения. Делаем её как и прежде, с помощью манипулирования временем:
animationTime += 1/stage.frameRate;
time = Math.pow(Math.sin( animationTime * 1), 7) * Math.PI;
Помните: при создании даже совсем небольшой анимашки, мы учимся делать что-то новое! Багаж знаний и умений пополняется. А что может быть лучше этого?! Верно - ничто!
Стоит отметить, что здесь есть не только движение эллипсов вниз-вверх, но и слабо заметное появление новых эллипсов снизу, и пропадание "в никуда" сверху. Вдобавок нижние эллипсы сильнее развёрнуты для достижения 3д-эффекта. Присмотритесь!
Итак, базовое расположение эллипсов - это обычный косинус :) Только у каждого эллипса он смещён по фазе вот так:
_y = cos( i / count * Math.PI ) * 90;
При этом значение каждого радиуса тоже описывается простенькой формулой:
_r = sin( i / count * Math.PI );
Чтобы сделать анимацию, сделаем вот такую "добавку": всего лишь один косинус, с параметром "время" внутри:
20 * cos(i / count * Math.PI * 1.5 + time * 2 * Math.PI / 2);
Чтобы упростить запись сделаем замену angle = i / count * Math.PI и получим вот такого монстра:
_y = cos( angle ) * 90 + 20 * cos(angle * 1.5 + time * 2 * Math.PI / 2);
_r = sin( angle );
А пропадание/добавление - это простое изменение размеров самих эллипсов. Изменим функцию для angle (которая напрямую используется в _r) и получим необходимый эффект:
angle = (i + time / 2) / count * Math.PI;
Ну и напоследок я еще решил сделать небольшой 3d-эффект, при котором нижние эллипсы чуточку развёрнуты к зрителю. Сделать это можно так: верхние эллипсы рисуются более вытянутыми, а нижние - сплюснутыми. Такая добавка (perspective) участвует только при отрисовке в качестве параметра height эллипса.
В итоге все формулы для отрисовки нашей анимации выглядят вот так:
angle = (i + time / 2) / count * Math.PI;
perspective = (1 - angle / Math.PI) * b / 3;
_y = Math.cos( angle ) * 90 + 20 * Math.cos(angle * 1.5 + time * 2 * Math.PI / 2);
_r = Math.sin( angle );
graphics.drawEllipse(-_r * a/2,
-_r * b/2 + _y,
_r * a,
_r * (b + perspective ));
Чего-то много математики вышло, сорри...)))
Цветок из кругов
А теперь немного разноцветной красивости.Здесь у нас куча кругов, которые сначала сходятся в один круг, а потом разлетаются в виде цветка. В итоге центры кругов всё время лежат на окружности, радиус которой постепенно увеличивается. Такие дела... математика выглядит для x и y центра каждого круга вот так:
Radius = r * (Math.cos(time) + 1) / 2;
circles[i].x = Math.cos(i / (count) * Math.PI * 2 + time * 1 ) * Radius;
circles[i].y = Math.sin(i / (count) * Math.PI * 2 + time * 1 ) * Radius;
Где
r - это максимальный расстояние, на которое разлетаются круги,
Radius - это текущее расстояние от центра,
i - номер круга, для которого мы всё и рассчитываем,
count - количество кругов... да-да, в демке можно менять их количество и увидеть, например, вот это:
animationTime += 1/stage.frameRate;
time = Math.pow(Math.sin( animationTime * 1), 7) * Math.PI;
И теперь в формулах используем везде time, который жуть какой нелинейный! (седьмая степень как никак)
Магия...
Исходный код
Ну вот и всё, исходник вооот здесь.Итого
Сегодня был как бы отдых, небольшие процедурные анимации, которые реально радуют глаз.Помните: при создании даже совсем небольшой анимашки, мы учимся делать что-то новое! Багаж знаний и умений пополняется. А что может быть лучше этого?! Верно - ничто!
0 коммент.:
Отправить комментарий