Byte/RE ИТ-издание

Программная анимация на Flash

Дмитрий Корепанов
dealer1@chat.ru

Программная анимация — что-то новенькое?

Программная анимация возникла, пожалуй, еще в те времена, когда компьютеры только появились. Но современные технологии придали ей новые особенности и сферы применения. Таким образом, явление нельзя назвать новым, но следует заметить, что сегодня создание программной анимации стало доступно более широкому кругу дизайнеров и программистов. Появились мощные и удобные средства, такие как пакеты Macromedia Director и Macromedia Flash. Существуют, конечно, и другие, но мы рассматриваем программную анимацию применительно к Интернету, а такую анимацию проще всего создавать средствами технологии Flash. Применение пакета Macromedia Director требует от разработчика более высокой квалификации; а кроме того, проигрыватель Shockwave несколько менее распространен в сети.

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

Удачно сделанная программная анимация бывает весьма красива, особенно если она связана с имитацией природных процессов. Окружающая нас природа — неисчерпаемый источник прекрасных идей для дизайнера. Как правило, это бывает хаотическая программная анимация. Генератор случайных чисел позволяет придать анимации постоянную изменчивость и непредсказуемость в каждый конкретный момент времени. В такой анимации есть что-то завораживающее. Смотреть на нее можно долго — так же, как на огонь, текущую воду, облака, дождь. Такая анимация приоткрывает нам фрактальную природу окружающего мира. Мир вокруг нас — это упорядоченный хаос. Этот хаос можно попытаться описать средствами математики и даже найти этому практическое применение. Клипы, сделанные с использованием методов программной анимации, бывают удивительно хороши и часто весьма малы по объему. Это одно из свойств фракталов — бесконечно сложные объекты описываются сравнительно простыми математическими соотношениями, за счет чего достигается компактность. Давайте же познакомимся с программной анимацией поближе.

Сферы применения

Чтобы не слишком отрываться от земли, попробуем сразу очертить основные сферы применения программной анимации. Можно выделить здесь следующие направления.

  • Игры, реализованные на Flash. Здесь программная анимация проявляется во
    всей красе. Усложнение поведения объектов и персонажей в игре в зависимости
    от происходящих событий и введение случайных составляющих позволяет создавать
    более интересные игры.
  • Элементы оформления сайтов для привлечения внимания посетителей. Сюда можно
    отнести и использование программной анимации в баннерах.
  • Элементы пользовательского интерфейса (динамические курсоры, кнопки и т.п.).
    С помощью программной анимации можно создавать интересные эффекты реакции
    на действия пользователя. От реализованных методами обычной анимации они отличаются
    тем, что могут реагировать более избирательно, например, отслеживая направления
    движения курсора мыши или частоту нажатий ее кнопки.
  • Элементы анимационных фильмов на Flash. Вы можете применять программную
    анимацию вместе с обычной, "ручной" анимацией. Программная анимация хороша
    для создания циклических фоновых процессов. В отличие от обычных циклов анимации,
    созданных вручную, можно получить более сложное и неповторяющееся движение,
    а также более интересные варианты движения в зависимости от действий пользователя.
  • Иллюстрации различных процессов для обучающих программ. Программная анимация
    хороша для иллюстрации некоторых физических процессов и для построения графиков
    математических зависимостей, диаграмм в формах голосования.

И наконец, еще одно из старейших применений компьютерной графики — построение изображений программным путем. Этот способ ограничен лишь вашей фантазией и познаниями в математике. Фрактальные алгоритмы позволяют (если подобрать соответствующую формулу) строить сколь угодно сложные картины, весьма реалистично отображающие объекты мира вокруг нас. Однако здесь сразу следует оговориться, что в случае технологии Flash этот способ имеет существенные ограничения в силу того, что простейший элемент картинки — это объект, который требует довольно много ресурсов для обработки и отображения.

Если вы решите использовать в своих работах программную анимацию, постарайтесь
не увлекаться готовыми эффектами. Исходных текстов в сети можно найти достаточно,
немало их на таком международном форуме, как http://www.flashkit.com.
Пытайтесь создавать что-то пусть более простое, но свое. Хороший эффект придумать
нелегко. Многие из них широко известны (равно как и их авторы), и прямое использование
таких эффектов сразу привлекает внимание и создает не очень благоприятное мнение
о том, кто их бездумно копирует. Впрочем, это относится к любому заимствованию.
Придумывайте интересные модификации уже существующих эффектов. Если вы разберетесь
в чужих кодах по-настоящему, вам будет легче найти способ их изменить, чтобы
получить что-то новое и интересное.

Основные подходы

Общий принцип при создании программной анимации состоит в том, чтобы в процессе воспроизведения ролика изменять свойства одного или нескольких объектов в соответствии с неким алгоритмом. Объекты могут быть созданы дизайнером на этапе проектирования или сгенерированы динамически.

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

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

О чем следует знать при создании программной анимации

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

Одним из основных ограничений следует признать недопустимость создания большого количества объектов динамически. Заметим, впрочем, что этого не следует делать и при ручном создании клипов. Вообще с увеличением числа объектов в сцене быстро становятся заметны "притормаживания" фильма. На более мощных машинах это происходит позднее, но рано или поздно происходит. А если вы ориентируетесь на пользователей с разной (в том числе не очень быстрой) техникой, то следить за началом этого процесса нужно особенно внимательно. При программной анимации ошибка в контроле над созданием и уничтожением клипов может привести если не к переполнению памяти, то наверняка к остановке (замедлению проигрывания) фильма.

Кроме того, технология Flash не очень приспособлена для выполнения математических вычислений. В пятой версии этот недостаток был частично устранен введением широко распространенных функций и приближением синтаксиса языка к традиционным языкам программирования типа C. Но следует все же признать, что проводить интенсивные математические вычисления на Flash не стоит. В то же время существуют очень интересные способы вычисления некоторых функций (sin, cos) графическим способом, через определение длины образцового отрезка при повороте на заданный угол.

Замечены и некоторые побочные эффекты, связанные с особенностями выполнения команд скрипта в текущем временном срезе и накоплением ошибки при последовательной многократной модификации свойств объекта.

Разбор примера "Облака"

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

За основу в этом примере была взята модель плывущих по небу облаков. Ниже мы покажем, как путем небольших изменений из этого можно сделать программную анимацию листопада. Минимально изменяя код, можно получить анимации текущей воды, волнующегося моря, снегопада и т.п. Отражая вполне реальные природные процессы, эта анимация сохраняет свою компактность — размер файла с плывущими облаками составляет около 3 Кбайт.

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

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

Кроме того, сразу следует внести в модель некоторые преувеличения. Дело в том, что скорость возникновения и исчезновения облаков невелика. В реальности нужно довольно долго наблюдать за небом, чтобы проследить процесс конденсации и растворения облака. Однако многие видели ускоренную съемку в научно-популярных фильмах, где облака текут во много раз быстрее. Небо от этого не перестает восприниматься как небо.

Итак, приступим. Для всех облаков мы будем использовать один клип-прототип. В нем мы нарисуем простую анимацию растущего из точки, плавно трансформирующегося и постепенно тающего облака. Весь этот цикл занимает 11 секунд, или 132 фрейма (при скорости воспроизведения 12 кадров/с). В данном случае лучше всего использовать анимацию форм. При небольшом количестве ключевых фаз мы получим плавную анимацию облака, перетекающего из одного положения в другое. Это то, что нужно, и прекрасно соответствует реальности.

Fig.1 Рис. 1. Основные фазы "жизни" облака.


На рис. 1 показано облако в его основных ключевых фазах. Эти картинки делаются очень просто. Облако представляет собой несколько соединенных между собой кривых, выгнутых в разной степени. Сначала создается облако в первом фрейме. Потом клавишей F6 можно создать еще четыре ключевых фрейма и в каждом из них изменить форму облака, чтобы она отличалась от соседних ключевых фаз. При этом нужно следить, чтобы форма не менялась слишком сильно, а число кривых оставалось постоянным. Это одно из условий успешной анимации формы без дополнительной головной боли с заданием точек подсказки. Чтобы видеть, все ли идет правильно, создайте клавишей F5 по нескольку штук простых фреймов между всеми ключевыми фреймами и следите по ним, не слишком ли вы увлеклись изменением формы объекта и не потеряна ли связь между соседними ключевыми фреймами (анимация формы должна происходить без перекручиваний и разрывов).

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

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

/:Count = /:Count-1;
removeMovieClip (_target);

Этот код довольно прост, но в нем скрыта одна из ключевых особенностей алгоритма: клип уничтожает сам себя! Это выполняется последней строкой кода, и это самое важное в нем. Не нужно беспокоиться о каждом отдельном созданном нами клипе. Мы будем только создавать клипы, а об уничтожении каждый из них позаботится сам. Это весьма изящная возможность контролировать хаос. О первой строке говорить особо нечего — она просто уменьшает глобальную переменную счетчика облаков, которую мы еще встретим ниже.

А пока вернемся к анимационной последовательности облака. Здесь сразу учтен и эффект движения облака под действием ветра (смещение по координате X). Этот эффект можно реализовать программно, но в данном случае нам хватит работы и без этого.

Для большей узнаваемости нужно подобрать для облака правильную заливку. Используйте радиальный градиентный переход от светло-серого к белому — и вы получите нужный эффект. Центр заливки лучше сместить в сторону.

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

Для начала заготовим клип, в котором будут создаваться наши облака. Назовем его, скажем, clouds. Разместите в этом клипе экземпляр нашего облака — подальше от центра и за пределами видимой области клипа. Поскольку этот экземпляр создан во время проектирования, то приведенный выше код уничтожать его не будет. Это просто образец облака для копирования.

Создайте еще один объект (это может быть объект типа Graphic) для фона. Мы выбрали градиент от белого к голубому радиальной формы.

В сцене будут присутствовать именно эти два объекта — фон и клип с облаками. Вы можете также сделать все в одном клипе, поместив фон в отдельный слой.

Теперь рассмотрим внимательнее код в нашем клипе с облаками. Здесь последовательность фреймов выглядит, как на рис. 2.

Fig.2
Рис. 2. Последовательность фреймов в клипе с облаками.


В первом фрейме находится код инициализации:

Count = 0;
MaxCountMatrix = 12;
MaxCount = MaxCountMatrix;
setProperty ("Obl01", _visible, 0);

Здесь устанавливаются значения счетчика облаков и некоторые переменные, используемые в дальнейшем для граничных условий генерации облаков. MaxCountMatrix содержит константу, которая позволяет определить степень заполнения клипа облаками. Однако число облаков в каждый момент времени будет случайным. MaxCountMatrix — это лишь отправная точка, служащая для стабилизации процесса. Образец делается невидимым. На видимость создаваемых на его основе экземпляров это не влияет — они создаются со свойствами по умолчанию, т. е. видимыми.

Во втором фрейме идет строка кода:

call ("CreateRandomClips");

Это вызов самой главной процедуры, в которой все и происходит.

Код предпоследнего фрейма выглядит следующим образом:

gotoAndPlay (2);

Это понятно — мы просто замкнули выполнение клипа, и он будет крутиться в петле. Кстати, число пустых фреймов, как можно будет увидеть дальше, тоже имеет некоторое значение и даже весьма существенное. Это число можно подобрать опытным путем либо вообще обойтись без этих фреймов, но изменить кое-что в коде последнего, главного в этой последовательности фрейма. Именно этот фрейм помечен меткой "CreateRandomClips". Он представляет собой по сути процедуру, задача которой — создать или НЕ создать новый объект облака и установить некоторым случайным образом его координаты и некоторые другие свойства (угол поворота, масштабирование по осям и т.п.). Если объект создан, то он отправляется в самостоятельное плавание и уничтожается сам в конце своего жизненного цикла. Ниже приведен код генерации облака:

1. if (Number(/:Count) == Number(MaxCount)) {
2. MaxCount = 10+Number(int(random(MaxCount-10)));
3. }
4. if (Number(MaxCount)<Number((MaxCountMatrix-MaxCountMatrix/5))) {
5. MaxCount = int(Number((MaxCountMatrix/2))+
	Number((random(MaxCountMatrix-MaxCountMatrix/2))));
6. }
7. CreatingProbability = random(MaxCount);
8. if (Number(/:Count)>14) {
9. CreatingProbability = 0;
10. }
11. if (Number(i)>10000) {
12. i = 0;
13. }
14. if (Number(/:Count)>15) {
15. MaxCount = int(random(MaxCountMatrix/3));
16. }
17. if (Number(/:Count)<5) {
18. MaxCount = int(random(MaxCountMatrix));
19. }
20. if (Number(/:Count)<Number(MaxCount)) {
21. if (Number(CreatingProbability)>7) {
22. /:Count = Number(/:Count)+1;
23. i = Number(i)+1;
24. duplicateMovieClip ("Obl01", "Ob" add i, i);
25. x = random(472)-235;
26. y = random(100)-124;
27. setProperty ("Ob" add i, _x, x);
28. setProperty ("Ob" add i, _y, y);
29. setProperty ("Ob" add i, _xscale, 60+Number(random(60)));
30. setProperty ("Ob" add i, _yscale, 80+Number(random(20)));
31. }
32. }

Выглядит не совсем понятно, верно? Впрочем, для программиста, которому уже приходилось играть вероятностями, все это довольно прозрачно.

Первая часть кода очень интенсивно использует оператор Random и выполняет задачу генерации некоторого числа, которое будет использовано во второй части кода для принятия решения: создавать или нет новый объект облака. Поскольку вторая часть весьма тривиальна, то мы рассмотрим сначала ее.

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

В строках 25-30 вычисляем и устанавливаем координаты объекта и его размеры. Принцип здесь прост: существует некоторое постоянное значение и к нему прибавляется случайная составляющая. Максимальное значение случайной составляющей задается числом в скобках функции random. Вы можете подобрать свои значения. Все зависит от размера вашего клипа и вашего представления о том, как это должно смотреться. Размеры объекта по осям изменяются только для того, чтобы сделать внешний вид объектов более разнообразным. Это простой и достаточно эффективный способ. При желании можно добавить еще поворот вокруг оси, но тогда движение облака под действием ветра нужно задавать программно (мы сделали это сразу анимацией формы) и отцентрировать фазы вокруг центра, чтобы поворот не слишком влиял на положение объекта. Можно задавать случайным образом и прозрачность облака, но это существенно увеличит требуемые для рисования ресурсы.

Теперь немного о первой части процедуры. Задача этой части кода — получить значение переменной CreatingProbability. Она служит ключом в принятии решения — создавать или не создавать объект. Таким образом, строки с 1 по 19-ю управляют числом облаков в клипе в каждый момент. Причем алгоритм построен так, что максимально возможное число облаков меняется в зависимости от того, сколько их уже имеется. Если облаков в данный момент мало, то их максимальное число увеличивается. Если облаков много, то оно уменьшается. Этим приемом вводится отрицательная обратная связь, позволяющая поддерживать число объектов в определенных пределах и в то же время менять его случайным образом. Переменная MaxCountMatrix — это константа, которая задается при запуске фильма и определяет густоту облаков. После этих пояснений разобраться в вышеприведенных строках будет уже не так сложно.

Этот способ управления генерацией облаков — не единственно возможный. Но он работает, и это главное. Вы можете поэкспериментировать и получить свои варианты приведенного алгоритма. В результате вам в голову обязательно придут интересные варианты использования данного подхода для создания хаотической анимации.

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

Теперь давайте рассмотрим один из вариантов модификации алгоритма. Хаотическая анимация "Листопад" была создана именно на основе анимации облаков методом преобразования. Сделав самые минимальные изменения, ее можно превратить в анимацию снегопада для новогоднего оформления сайта — достаточно лишь заменить листья снежинками.

Мы не будем подробно рассматривать все строки кода этого примера. Обозначим лишь основные направления, по которым шло преобразование. Во-первых, листья движутся в основном по вертикали. Поэтому координаты для начального появления листьев выбираются в верхней части клипа. Сам клип построен вертикально. Поскольку одним листом обойтись трудновато, как его ни изменяй в размерах и ни поворачивай, то было сделано семь различных по форме и раскраске образцов. Вид образца для дублирования определяется случайно той же функцией random(7), дающей число от 0 до 6. Все виды листьев можно разместить в разных фреймах одного клипа-образца и при создании экземпляра просто переходить на соответствующий фрейм.

Еще одна особенность этой анимации — поведение каждого листа при падении. Лист крутится и может двигаться в разные стороны по зигзагообразным траекториям. Эти траектории гораздо сложнее, чем траектория движения облака под действием ветра. Здесь оправданно применить инкапсуляцию поведения объекта. Лист должен сам контролировать свое поведение и траекторию. Сделать это не так сложно: в клипе размещается трехкадровый цикл (полагаю, вы уже знаете, что это такое). Весь контролирующий код размещен во втором кадре. Первый служит, как обычно, для задания начальных значений переменных. Третий замыкает цикл. Самым простое здесь — реализация падения листа. Для этого надо только увеличить координату Y; силой притяжения можно пренебречь, так как лист — по сути парашют в миниатюре. Уничтожение объекта выполняется самим объектом, как в примере с облаками, но не в последнем кадре анимационной последовательности, а по истечении срока жизни листа. Этот срок хранится в особой переменной и уменьшается в каждом кадре. Хаотичность движения листа создается путем перемещения по оси X и вращением, причем меняется как скорость движения или вращения, так и направление. Для этого вводятся специальные переменные. Одни содержат шаг перемещения по оси X или шаг угла поворота. Другие, указатели направления движения и вращения, могут принимать лишь два значения (скажем, 1 и -1). Подбором вероятностей можно добиться нужного поведения листа. Вероятность изменения направления лучше выбирать не более 10%, чтобы объект какое-то время двигался в одном направлении, и это движение "прочиталось". В противном случае движение будет слишком дерганым.

Вот код во втором фрейме:

livingTime = livingTime-1;
   call ("transform1");
if (Number(livingTime)<1) {
call ("removeClip");
}
if (Number(_y)>600) {
   livingTime = 0;
}

Здесь видно, что лист уничтожается и по достижении определенной координаты по оси Y. В принципе это избыточно и здесь приводится лишь для примера. Можно оставить один из этих вариантов (любой).

Приведем одну из процедур для иллюстрации контроля за свойствами листа:

 setProperty (_target, _y, Number(_y)+5);
call ("transform2");
// ====
pr1 = random(100);
if (Number(pr1)<Number(rotateChange)) {
   if (Number(rotateDirection) == Number(-1)) {
      rotateDirection = 1;
   } else {
      rotateDirection = -1;
   }
}
// ====
pr1 = random(100);
if (Number(pr1)>Number(rotateStepChange)) {
   rotateStep = random(30);
}
// ====
angle = Number(angle)+Number(rotateStep*rotateDirection);
setProperty (_target, _rotation, angle);

Здесь обрабатывается падение листа вниз, вызывается еще одна процедура для контроля движения по оси X, определяется направление вращения и шаг вращения и, наконец, совершается поворот. Процедура для контроля перемещения по оси X выглядит очень похоже.

В результате реализации приведенного кода листья будут падать, плавно вращаться то в одну, то в другую сторону и скользить в горизонтальном направлении. Траектории движения будут схожи со спиральным движением реального падающего листа.

* * *

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

Вам также могут понравиться