Опубликован: 23.12.2005 | Уровень: специалист | Доступ: платный | ВУЗ: Московский физико-технический институт
Лекция 3:

Клипы и ролики. Специальные возможности языка

Дублирование клипов, создание пустых клипов

Мы с вами уже познакомились с различными аспектами создания клипов (символов и экземпляров) в процессе ручного редактирования ролика. Однако экземпляры клипов можно создавать и программно. Для программного создания клипов существует три способа. Два из них предназначены для того, чтобы создавать экземпляры символов, имеющихся в библиотеке (один из них - duplicateMovieClip - мы рассмотрим сейчас, другой - attachMovie - в девятой главе). Третий ( createEmptyMovieClip ) создает пустой клип, который в дальнейшем можно использовать для разных целей: рисовать в нем программно (см. главу 10) или прикреплять к нему дочерние клипы при помощи attachMovie. Этот способ мы также подробнее рассмотрим в данном подпараграфе.

Итак, что же представляет собой функция duplicateMovieClip? Она предназначена для дублирования экземпляров клипов, имеющихся в нашем ролике, и принимает три аргумента. Первый - это путь к тому экземпляру, который мы собираемся продублировать (путь передается в том же формате, в котором хранится путь к клипу в свойстве _target ). Второй аргумент - имя нового экземпляра (путь к нему будет отличаться от пути к исходному экземпляру только этим именем; то есть владельцем дубликата будет тот же клип, который является владельцем исходного экземпляра). Третий аргумент - так называемая глубина уровня. Впрочем, это название не полностью соответствует смыслу параметра: дело в том, что чем больше это число, тем выше в z-порядке расположен клип. Заметим также, что упорядочение по глубине относится только к экземплярам, которыми владеет один конкретный клип (владельцем, в частности, может быть и корневой клип ). Если же владельцы клипов разные, то z-порядок будет определяться тем, как упорядочены владельцы.

Сделаем здесь важное терминологическое замечание. Мы чуть ранее говорили о динамической подгрузке готовых роликов, и там тоже фигурировали номера уровней. Так вот, номера уровней для роликов - это совсем не то, что номера уровней для клипов. По влиянию на z-порядок самым "старшим" является уровень ролика, затем расположение клипов -владельцев в z-порядке, и лишь затем уже идет уровень подгрузки отдельных клипов (который надо учитывать, если сравниваемые по расположению в z-порядке клипы принадлежат одному владельцу).

Итак, попробуем дублирование клипов в действии. Создадим символ с нарисованным внутри прямоугольником (без рамки; для создания такого прямоугольника в панели рисования удобно выбрать "пустой" цвет линий - его символизирует зачеркнутый квадратик в правой верхней части палитры). Сделаем один экземпляр этого символа и присвоим экземпляру имя sourceClip. Далее напишем в первом кадре корневого клипа следующий код:

// Скрываем исходный клип, чтобы он не портил нам картинку
sourceClip._visible = false;
// Делаем 10 копий исходного клипа, причем каждую
// следующую сдвигаем вниз и вправо
for (var i=1; i<=10; i++){
   duplicateMovieClip("sourceClip", "duplicated" + i, i);
   setProperty("duplicated" + i, _x, 50 + 20*i);
   setProperty("duplicated" + i, _y, 50 + 20*i);
}

Запускаем ролик и наблюдаем следующую приятную для глаза картину:


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

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

Вот код, который выполняет сию задачу:

// Скрываем исходный клип, чтобы он не портил нам картинку
sourceClip._visible = false;

// Делаем 10 копий исходного клипа, причем каждую
// следующую сдвигаем вниз и вправо
for (var i=1; i<=10; i++){
   duplicateMovieClip("sourceClip", "duplicated" + i, i);
   setProperty("duplicated" + i, _x, 50 + 20*i);
   setProperty("duplicated" + i, _y, 50 + 20*i);
}

// Второй исходный клип тоже скрываем
anotherSourceClip._visible = false;

// Делаем пять копий второго клипа и убеждаемся в том,
// что они занимают место копий первого клипа
// с теми же номерами уровней
for (var i=2; i<=10; i+=2){
   duplicateMovieClip("anotherSourceClip", "anotherDup" + i, i);
   setProperty("anotherDup" + i, _x, 50 + 20*i);
   setProperty("anotherDup" + i, _y, 50 + 20*i);
}

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


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

createEmptyMovieClip("empty1", 3);

(которая означает, что мы создаем пустой клип с именем empty1 на уровне 3), мы получим вот какую картинку:


Один прямоугольник просто исчез! И мы, разумеется, понимаем, почему так произошло: он был заменен пустым клипом, занявшим его уровень.

Теперь давайте рассмотрим пару дополнительных полезных методов класса MovieClip . Первый из них - метод swapDepths. Передается в него либо путь к некоторому клипу, либо уровень, на котором этот клип лежит. При этом указываемый клип должен обязательно иметь того же родителя, что и клип, метод которого мы вызываем. Результатом действия этого метода является обмен двух наших клипов в z-порядке.

А можно ли узнать, на каком уровне лежит некий произвольный клип? Оказывается, да, и для этого служит метод getDepth. Никаких аргументов ему передавать не надо, просто вызовите его для нужного клипа и он вернет вам номер уровня.

Давайте посмотрим, как действует этот метод, и для этой цели допишем к последнему примеру следующие четыре строчки:

trace("duplicated7.getDepth() = " + duplicated7.getDepth());
trace("anotherDup4.getDepth() = " + anotherDup4.getDepth());
trace("sourceClip.getDepth() = " + sourceClip.getDepth());
trace("anotherSourceClip.getDepth() =
   " + anotherSourceClip.getDepth());

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

duplicated7.getDepth() = 7
anotherDup4.getDepth() = 4
sourceClip.getDepth() = -16383
anotherSourceClip.getDepth() = -16381

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

Давайте теперь используем наши знания о методе swapDepths для того, чтобы поменять местами (в z-порядке ) сначала два клипа, созданных программно, а затем и клип, созданный в редакторе, с клипом, созданным программно. Добавляем к нашему примеру следующий код:

anotherDup10.swapDepths(anotherSourceClip.getDepth());
trace("anotherDup10.getDepth() = " + anotherDup10.getDepth());
trace("anotherSourceClip.getDepth() = " +
   anotherSourceClip.getDepth());

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

anotherDup10.getDepth() = -16381
anotherSourceClip.getDepth() = 10

Работает с отрицательными уровнями и функция createEmptyMovieClip: если мы вставим перед тремя последними строками кода вызов

createEmptyMovieClip("empty2", anotherSourceClip.getDepth());

то в консоли вместо предыдущих двух строк увидим

anotherDup10.getDepth() = 10
anotherSourceClip.getDepth() =

то есть клип anotherSourceClip был замещен пустым клипом empty2, и поэтому обмен уровнями между клипами anotherSourceClip и anotherDup10 не произошел. Интересно, что функция, предназначенная специально для удаления клипов, - removeMovieClip (в качестве аргумента ей передается путь к удаляемому клипу ) в состоянии удалять лишь клипы с положительными значениями уровня. Наконец, давайте проверим, может ли функция duplicateMovieClip, создавая дубликат какого-то клипа, расположить его на отрицательном уровне. Добавляем к нашему примеру еще три строчки:

duplicateMovieClip("anotherSourceClip", "anotherDup__", -10);
setProperty("anotherDup__", _x, 150);
setProperty("anotherDup__", _y, 30);

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

алексеи федорович
алексеи федорович
Беларусь, рогачёв
Тамара Ионова
Тамара Ионова
Россия, Нижний Новгород, НГПУ, 2009