Список отображения (display list) в ActionScript 3

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

Например, movieclip мог быть взят из другого источника, дублирован и затем помещен на сцену в IDE (среда разработки, Flash Professional, например) или создан абсолютно с нуля с помощью ActionScript. C текстовыми полями та же история. Когда дело доходило до растровых объектов (bitmap), видео, компонентов и прочего, то возникало чувство, что все они создавались на разных планетах, а затем помещались во Flash, чтобы как-то работать с другими. Словом, царил некоторый беспорядок, с которым нужно было что-то делать.

На этом уроке Вы узнаете как была решена эта проблема в ActionScript 3, а также:

  1. Что такое список отображения (display list) в ActionScript 3
  2. Вспомните, что такое объект отображения (display object)
  3. По какому принципу устроен список отображения
  4. Как поместить один объект в другой объект с помощью AS 3

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

Cоздание объектов типа sprite, movieclip или текстового поля в ActionScript 3 происходит одинаково. Все они создаются с помощью оператора new. Например:

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

В предыдущих уроках было показано, что после создания movieclip или sprite можно рисовать непосредственно в них, т.е. наполнять их определенным содержанием. Например:

Но, если делать только так, то Вы мало что сможете увидеть. Поэтому сейчас самое время поговорить о списках отображения (display list).

Что такое список отображения (display list) в ActionScript 3

Для AS3 список отображения (display list) — это новый термин. Но, если у Вас уже есть опыт работы во Flash, то, наверняка, Вы успели с ним познакомиться. Представляйте его в виде дерева визуальных объектов, которые находятся в Вашем флеш-ролике.

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

Для примера рассмотрим простую композицию из 4-х объектов: строчки текста и трех фигур.

display-list-before

На самом деле, во Flash, структурно, я организовал все это чуть сложнее, чем мы видим. Каждая фигура помещена в отдельный movieclip со своим именем: star, rect и circle, а они, в свою очередь, находятся внутри movieclip figures. На рисунке ниже это показано.

Как устроен список показа во Flash

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

В ActionScript 3, созданный movieclip, sprite или другой объект отображения НЕ добавляется на сцену автоматически.

В примере, показанном выше (mySprite), у объекта типа sprite нет родителя, т.е. объекта в который он помещается. Мы можем управлять им и без включения в список отображения.

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

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

Класс документа (document class) представляет из себя основание дерева или прадедушку всех объектов отображения (display object). Он виден по умолчанию и при работе, практически, над любым флеш-роликом Вы начинаете с того, что добавляете ему потомков. В предыдущих примерах было показано, что для того чтобы сделать sprite или любой другой визульный объект видимым нужно вызвать метод addChild() и передать ему в виде параметра вновь созданный объект:

Если Вы хотите увидеть этот код в работе, то поместите его в базовый класс, о котором рассказывалось в предыдущих уроках. Заметьте, что sprite будет помещен в точку 0,0 на осях координат. Чтобы изменить его положение на сцене используйте его свойства x и y.

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

Чтобы удалить объект из списка отображения нужно вызвать метод removeChild(), которому в виде параметра передается имя объекта.

О чем нужно помнить и знать

Первое. Удаление объекта со сцены НЕ уничтожает его! Он продолжает существовать точно в таком же состоянии, что и до удаления, и будет делать это после добавления его в список отображения снова. Другими словами, если Вы нарисовали или поместили что-то в объект отображения (display object), а затем удалили, то это не значит, что Вам нужно снова рисовать или загружать те же объект(ы) для помещения в список отображения. Они продолжают там находиться.

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

Следующий пример демонстрирует взаимосвязь родитель-потомок:

Как видно из кода этот класс создает три объекта типа sprite: parent1, parent2 и ball. Sprit’ы-родители непосредственно добавляются на сцену и в них рисуются квадраты. Sprite с именем ball добавляется в parent1. В результате он находится на сцене и мы его видим.

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

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

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

Итоги

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

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

  1. В чем разница между списком отображения и объектом отображения в AS3?
  2. Как поместить один объект в другой?
  3. Что происходит с объектом после удаления его со сцены?
  4. Нужно ли создавать заново или импортировать объект, если Вы его удалили, а затем снова хотите поместить на сцену?

Жду вопросов. Задавайте в комментариях. Постараюсь ответить на все.

Список отображения (display list) в ActionScript 3: 16 комментариев

  1. Весь код не буду копировать, только то что изменил ******************************************************************************************** public function onBallClick(event:MouseEvent):void { parent2.addChild(ball); ball.removeEventListener(MouseEvent.CLICK, onBallClick); ball.addEventListener(MouseEvent.CLICK, on_BallClick); } public function on_BallClick(event:MouseEvent):void { parent1.addChild(ball); ball.removeEventListener(MouseEvent.CLICK, on_BallClick); ball.addEventListener(MouseEvent.CLICK, onBallClick); } ********************************************************************************************

        1. А так? *** public function onBallClick(event:MouseEvent):void { parent2.addChild(ball); ball.addEventListener(MouseEvent.CLICK, on_BallClick); } public function on_BallClick(event:MouseEvent):void { parent1.addChild(ball); ball.removeEventListener(MouseEvent.CLICK, on_BallClick); }

          1. В связи с переносом этого сайта на другую CMS неделю назад, я еще не опубликовал все комментарии, которые были на этой странице до этого. Так вот, на мой взгляд самое оптимальное решение в своем комментарии предложил Евгений. Вот оно: public function onBallClick(event:MouseEvent):void { if(ball.parent == parent2) parent1.addChild(ball); else parent2.addChild(ball); } Здесь, конечно, используется свойство parent, указывающее на родительский объект, о котором Вы возможно и не знали. Но зато теперь будете знать!

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

    1. Продолжение будет! Пытаюсь найти время для того, чтобы продолжить. Задача не простая… Думаю, что в ближайшие месяца два бесплатный вводный курс сделаю.

  3. function onBallClick(event:MouseEvent):void{ parent2.addChild(ball2); ball2.removeEventListener(MouseEvent.CLICK, onBallClick); ball2.addEventListener(MouseEvent.CLICK, onBallClick2); } function onBallClick2(event:MouseEvent):void{ parent1.addChild(ball2); ball2.removeEventListener(MouseEvent.CLICK, onBallClick2); ball2.addEventListener(MouseEvent.CLICK, onBallClick); }

  4. А у меня приведённый пример вообще не работает. Compiler errors: Scene 1, Layer ‘Layer 1’, Frame 1, Line 1 1037: Packages cannot be nested.

  5. Если немного усовершенствовать код, то можно заставить красный мячик прыгать туда-сюда из одного квадрата в другой, кликая на нем мышью. Как это сделать попробуйте догадаться сами.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *