Циклы в ActionScript 3

В предыдущих уроках курса «Основы анимации в ActionScript 3» Вы уже достаточно хорошо познакомились с основами для того, чтобы приступить к практическому программированию в AS3. Надеюсь, что Вы также установили Flash Professional на свой компьютер. Давайте приступим.

В этом уроке Вы узнаете:

  1. О циклах в ActionScript 3
  2. Как создается программная анимация с помощью циклов
  3. Как избежать ошибки, которую совершает 99% начинающих
  4. Об очень важной концепции цикла кадров

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

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

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

  • кадр 1:  мяч находится в 15 пикселах от левой границы сцены;
  • кадр 2:  мяч находится в 30 пикселах от левой границы сцены;
  • и т.д.

Flash Player получает эти данные и в соответствии с таким описанием воспроизводит сцену. Схема на рисунке ниже показывает этот процесс.

Но если говорить о динамической программной анимации, то она должна быть представлена так:

Как видите, здесь отсутствует концепция покадровой анимации. Программная же анимация может (и, как правило, так и происходит) реализовываться в одном кадре!

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

Второе. Вы устанавливаете правила. Они могут быть очень простыми, как, например, следующее: мяч перемещается на 5 пикселов вправо. Либо сложными, т.е описываться десятками строчек кода. Вы увидите достаточно примеров в этом курсе, как первого, так и второго.

Применение созданных Вами правил в итоге приведет к новому состоянию сцены — это новое описание, которое будет обработано и показано. Затем Вы применяете те же правила снова и снова.

Заметьте, что применяются одни и те же правила. У Вас не будет одного набора правил для первого кадра, второго набора для второго кадра и т.д. Поэтому Вашей главной задачей будет определение полного списка правил, которые опишут любую возможную ситуацию, возникающую на сцене. Что, например, случится, если Ваш мяч докатится до правой границы сцены? В Вашем списке правил должно находиться такое, которое опишет эту ситуацию. Если Вы хотите чтобы пользователь взаимодействовал своей мышью с мячом, то Вы должны установить правило и для такой ситуации.

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

Эти правила, по сути, являются командами ActionScript. Любое их них может быть как очень простым — одна строчка кода, так и довольно сложным — состоять из нескольких или множества директив.

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

ball.x = ball.x + 10;

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

ball.x += 10;

Оператор += говорит: добавьте значение справа к переменной слева и присвойте результат этой переменной.

А вот более сложное правило, которое мы будем разбирать позднее в этом курсе:

var dx:Number = mouseX - ball.x;
var dy:Number = mouseY - ball.y;
var ax:Number = dx * spring;
var ay:Number = dy * spring;
vx += ax;
vy += ay;
vy += gravity;
vx *= friction;
vy *= friction;
ball.x += vx;
ball.y += vy;
graphics.clear();
graphics.lineStyle(1);
graphics.moveTo(ball.x, ball.y);
graphics.lineTo(mouseX, mouseY);

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

Итак, как же заставить работать такой цикл? Для начала я покажу Вам очень характерную ошибку, которую совершают 99% начинающих программистов (я в свое время тоже не был исключением). Она кроется в самой структуре цикла, будь то for или while.

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

for(var i:uint = 0; i < 500; i++){
  ball.x  = i;
}

Как видите все просто.

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

i++ увеличивает значение переменной i на 1 после полного прохождения очередного цикла, начиная с 0, затем 1, 2, 3, 4 и т.д. Каждый раз это новое значение присваивается ball.x, перемещая его по сцене слева на право. Когда оно достигает 500, то i < 500 будет false и цикл прекратит свою работу.

Если Вы совершите такую же ошибку, то увидите, что мяч не будет двигаться по сцене, он просто сразу окажется справа. Почему же мы не видим его перемещающимся и проходящим последовательно все точки от 0 до 499?

В действительности он их проходит!

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

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

Вот последовательность действий, которые осуществляет Flash:

  • Определить местоположение для всех объектов, которые находятся в текущий момент на сцене, на всех уровнях, слоях, загруженных movie clip’ах и т.д.
  • Обработать весь код ActionScript, вызываемый в этом кадре на любом слое или уровне, для любого movie clip или кнопки, или помещенного внутрь любого movie clip, вне зависимости от того как глубоко.
  • Проверить наступил ли момент для показа этого кадра. Если частота кадров Вашего ролика равна 20 кадрам в секунду, то Flash сделает это не раньше чем через 50 миллисекунд с момента показа последнего кадра. И если это так, то он покажет кадр, который только что обработал и перейдет к следующему. Если же нет, то он будет ждать до тех пор пока не пройдет установленное для этого время.

Вы должны запомнить пару вещей, которые касаются этого временного фактора (timing):

  • Первое. Установленной частоте кадров сильно доверять нельзя. Никогда этого не делайте, особенно в ситуациях, когда временной фактор очень важен в создаваемой Вами анимации.
  • Второе. Бывают случаи, когда время на рендеринг и обработку кода ActionScript превышает время, определенное для конкретного кадра. Вам не нужно по этому поводу беспокоиться. Ваш код не будет как-то обрезан или частично усечен. Flash не перейдет к следующему шагу пока не завершит предыдущий, даже если он начнет уменьшать частоту кадров своими действиями. Он будет просто ждать до 15 секунд, пока обрабатывается Ваш код и если этот процесс не закончится раньше — покажет следующее сообщение «A script is causing the player to run slowly…». Что означает «Код замедляет работу плейера…».

В предыдущем примере, Flash ждал окончания цикла прежде чем перейти к следующему кадру. Он обновляет экран непосредственно перед этим действием. Вот почему Вы были свидетелем скорее прыжка мяча, а не плавного движения.

Решение проблемы: Вам необходимо разбить цикл по кадрам, чтобы получить именно такое движение.

Цикл кадров

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

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

Идея цикла кадров была реализована еще в самых первых версиях Flash, когда ActionScript не был еще настолько мощным языком программирования, как сейчас. Она заключается в следующем: Вы записываете код ActionScript в определенный кадр, а затем, в следующий кадр, помещаете какую-нибудь команду, обычно gotoAndPlay. Эта команда возвращает воспроизведение к предыдущему кадру, создавая бесконечный цикл между ними. В результате, каждый раз при попадании головки Flash Player’а на кадр с кодом он будет обрабатываться.

Здесь важно понимать, что поскольку у нас есть два кадра, то:

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

Именно этими действиями и создается анимация.

Давайте рассмотрим простой пример реализации этой концепции.

Допустим, Вы разместили на сцене экземпляр символа с именем ball (мячик). В первом кадре Ваш код мог бы быть следующим:

ball.x ++;

Во втором таким:

gotoAndPlay(1);

В силу того, что этот пример слишком простой (у нас создано всего лишь два кадра), во втором кадре такую команду писать и не нужно, т.к. шкала времени автоматически вернется к первому.

Как вариант, Вы можете создать анимацию из трех кадров, где:

  • первый кадр является инициализирующим
  • во втором кадре будут расписаны основные действия
  • третий кадр будет возвращать ко второму
gotoAndPlay(2);

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

Подобный подход, хоть и является устаревшим — он был основным приемом работы во Flash 5 и более ранних версиях программы — до сих пор работает безупречно.

Подобный разбор различных фаз анимации:

  • инициализация
  • действия
  • цикл

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

Итоги

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

Контрольные вопросы по материалу урока

  1. Чем отличается реализация покадровой анимации во Flash от программной?
  2. Что такое цикл? Как он записывается?
  3. При каком условии программная анимация может быть осуществлена?

Все возникшие вопросы по материалу урока задавайте в комментариях.

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