06 апреля 2017

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

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

А это вообще процедурная анимация?

Да, частицы и их поведение тоже относят к процедрным анимациям. Но так как они получили безумно широкое применение, то в итоге "частицы" стоят особняком в процедурных анимациях... поэтому я и решил немного остановиться на том, что это такое и зачем нужно!

Что такое "частицы" вообще?

Очень часто в анимациях у нас движется не один объект, а как бы их скопление. Дым, дождь, огонь, снег... При этом сам эффект состоит из движения множества небольших объектов. Частичка дыма, капелька воды, искра огня, маленькая снежинка - всё это примеры одной частицы. Они могут двигаться независимо друг от друга, или влиять на передвижение соседей.


Зачем нужны "частицы"?

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

Сегодняшний "сахар"

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

Вся идея движения в нескольких предложениях

Начну с самого главного - с логики движения. Итак, приготовьтесь!
Сама частица просто проверяет трёх своих соседей под собой.



  • Если прямо под ней никого - то движемся вниз. 
  • Если занято - проверяем слева-внизу, свободно - движемся. 
  • Если слева-внизу уже занято - то проверяем справа-внизу - свободно? - ок, падаем вниз. 
  • Занято? Значит вообще остаемся на месте.

Вот и вся магия... Никакой физики и формул! Вообще!



Как хранить частицы

Да, самое сложное здесь - это конкретная реализация и способ хранения частиц. Всё упирается в такой вопрос: "Как узнать, есть ли частица под другой частицей?" Перебор всех подряд? Да, можно было бы проверять все частицы... но это слишком долго. Поэтому мы создадим сетку (двумерную матрицу/массив). В каждой ячейке может быть только одна частица. Ссылку на неё и будем хранить.
Тогда проверка нижних соседей выглядит безумно просто:
Частица слева:   matrix[i - 1][j + 1]
...по центру:        matrix[i][j + 1]
...справа:  matrix[i + 1][j + 1]

Когда создавать частицы

С этим всё проще. Обычно делают так - запускаем таймер и через несколько миллисекунд создаем новую частицы, а таймер при этом перезапускаем, чтобы "тикал" с самого начала. Так он будет отсчитывать равные промежутки времени, через которые будем создавать и запускать новую частицу... а лучше - сразу несколько частиц!

Развитие идеи

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

  • Липкий снег. Если коснулись другой частицы - то останавливаемся.
  • Вода. Если внизу занято, то двигаем частицу влево.
  • Огонь. Частицы движутся вверх и не взаимодействуют друг с другом.
И так далее... вариантов развития этой идеи реально много! Экспериментируйте!

Исходный код

Мне так нравился WonderFL... и вот - его закрыли :(
Поэтому пока положу исходники вот так. Жмякаем "copy code to clipboard"... и всё! А затем просто копируйте код на первый кадр в пустой проект и наслаждаемся сахаром :)

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

0 коммент.:

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