[ предыдущая страница ] [ следующая страница ] [ содержание ]

6.4. Применение циклов

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

6.4.1. Работа с массивами данных

Основное применение программных циклов в языке ActionScript - это вычисления и работа с массивами данных. Например, если имеется массив myarray из 100 элементов, которые нужно обнулить, это можно сделать с помощью цикла for:

for (i=0;i<100;i++) {
   myarray[i] = 0;
}

В данном случае переменная i выступает как счетчик цикла и одновременно используется для задания индекса элемента массива. В некоторых случаях можно заставить "счетчик" принимать еще более активное участие в циклических вычислениях. Например, если нужно вычислить сумму всех четных чисел от 128 до 256, можно написать такой цикл:

res = 0;
for (i=128;i<=256;i+=2) {
   res += i;
}

В результате искомая сумма будет содержаться в переменной res.

Все три значения, указываемые в скобках при операторе for: начальное значение, условие выхода и переход к следующему шагу, - являются необязательными. Можно даже написать for(;;) для организации бесконечного цикла. Надо только не забыть предусмотреть где-нибудь в теле цикла оператор break для выхода из него.

Специальная форма цикла

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

а = new Object();
а = {ll:60,lr:40,rl:40,rr:60);

(такой объект, если помните, может использоваться для трансформации звука), то можно "пройтись" по всем его элементам, например, вот так:

for (x in a) {
   trace (х+"="+а[х]);
}

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

ll=60;
lr=40;
rl=40;
rr=60;

Как видите, оператор trace по очереди применен к каждому из элементов объекта a.

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

Откройте новый ролик и создайте в нем мувик с любым содержимым. Поместите в рабочую область четыре экземпляра этого мувика. Откройте окно сценария в первом (и единственном) кадре. Поместите туда такой код:

for (x in _root) {
   if (typeof(_root[x])=="movieclip") {
      _root[x]._x = Math.random()*550;
      _root[x]._y = Math.random()*400;
   }
}

Поскольку все наши мувики расположены в основном ролике, в качестве родительского объекта мы здесь указали _root. Обратите внимание на форму записи, используемую, когда имя элемента объекта представлено какой-либо переменной (в данном случае это x). Для обращения к каждому из экземпляров мувика нам пришлось оформить его имя как индекс массива, заключив его в квадратные скобки. Если бы мы написали вместо _root[x] более "привычное" _root.x, ничего бы не получилось, поскольку в этом случае x воспринимается не как имя переменной, а как имя реального объекта - экземпляра мувика.

Таким образом, приведенный сценарий в цикле присваивает координатам каждого объекта, являющегося мувиком, случайные значения. Для определения типа объекта используется оператор typeof, который всегда возвращает строковое значение, обозначающее тип аргумента. Это может быть movieclip, string, function или object.

6.4.2. Роль программных циклов

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

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

do {
   _х++;
} while(!key.isDown(key.SPACE));

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

6.5. Трассировка и отладка сценария

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

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

Ну, с синтаксическими ошибками в программе Flash все ясно. Во-первых, нажав клавиши CTRL+T в окне ввода сценария, можно заранее проверить его синтаксис. При этом в окно Output (Вывод) выводятся сообщения обо всех найденных ошибках, если таковые имеются. Во-вторых, даже если не проверить синтаксис и запустить просмотр ролика, синтаксис сценария проверяется по ходу выполнения, и вы также получите сообщения обо всех ошибках в окне Output (Вывод).

6.5.1. Трассировка сценария

Как всегда, несколько сложнее дело обстоит с ошибками логическими. Чтобы их "выловить", можно пользоваться так называемой трассировкой программы. Как мы уже несколько раз упоминали, оператор trace выводит в окно Output (Вывод) все, о чем мы его попросим.

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

for (x in _root) {
   if (typeof(_root[x])=="movieclip") {
      _root[x]._x = Math.random()*550;
      _root[x]._y = Math.random()*400;
   }
}

а

for (x in _root) {
   if (typeof(x)=="movieclip") {
      x._x = Math.random()*550;
      x._y = Math.random()*400;
   }
}

то есть ошибочно обозначить объект как переменную x, а не как элемент объекта (_root[x]), можно увидеть, что ожидаемого случайного разброса мувиков не происходит.

6.5.2. Анализ сценария путем трассировки

Чтобы понять, в чем здесь дело, надо вставить оператор trace в блок оператора if, чтобы понять, выполняется ли он вообще:

for (x in _root) {
   if (typeof(x)=="movieclip") {
      trace ("блок if");
      x._x = Math.random()*550;
      x._y = Math.random()*400;
   }
}

Просмотрев мувик, мы увидим, что в окно Output (Вывод) ничего не выводится. Значит, блок при операторе if не выполняется, так как ни разу не выполняется условие if. А условие это сравнивает значение typeof(x) со строкой "movieclip". Чтобы понять, почему это условие не выполняется, вставим оператор trace в цикл и заставим его выводить значение typeof(x):

for (х in _root) {
   trace (typeof(х));
   if (typeof(x)=="movieclip") {
      x._x = Math.random()*550;
      x._y = Math.random()*400;
   }
}

Просмотрев ролик, мы убедимся, что в окно Output (Вывод) пять раз выводится слово "string". Проанализировав, почему так происходит, можно догадаться проверить синтаксис обращения к элементам объекта _root и понять, что нужно писать _root[x], а не просто x.

6.5.3. Применение оператора trace

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

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

[ предыдущая страница ] [ следующая страница ] [ содержание ]
Hosted by uCoz