Просто об ActionScript 3. Часть 2

Итак, начиная с этой части, мы приступаем к практическим действиям. В качестве базовой (в силу бесплатности) возьмем интегрированную среду разработки (IDE) FlashDevelop (http://www.flashdevelop.org), для работы в которой нам понадобится дополнительно скачать Flex SDK с сайта Adobe (http://www.adobe.com/products/flex.html) и Java Runtime Environment (JRE) с сайта http://java.sun.com/. Этот вариант хорошо подойдет для демонстрации работы с ActionScript3, при этом вам не надо будет заботиться о получении лицензии после истечения срока действия trial-версии Flex/Flash Builder. Итак, устанавливаем сначала JRE, затем Flex SDK (JRE нужен именно для него), а затем Flash Develop. Запускаем последний. Если Flex SDK не была найдена FlashDevelop на автомате, заходим в пункт главного меню Tools, выбираем пункт Program Settings… В открывшемся окне находим в закладке AS3 Context надпись Installed Flex SDK, нажимаем на кнопку напротив и указываем путь к Flex SDK.

В качестве дополнительной литературы могу порекомендовать две книги, которые есть на русском языке: «ActionScript 3.0 для Flash» Колина Мука и «ActionScript 3.0. Сборник рецептов» Лота, Шалла и Питерса. В первой все изложено очень подробно, включая объяснение постулатов ООП для новичков, там даже программы начинают писать с 7-й главы, во второй вы можете найти довольно много практических примеров. Плюс к этому на самом сайте Adobe можно найти большое количество полезной и актуальной информации.

Создаем свой первый AS3-проект

Заходим в опцию главного меню Project и выбираем пункт New Project. В результате открывается окно создания нового проекта, в котором нужно выбирать тип проекта (в данном случае нам подойдет вариант AS3 Project), указать его название и папку, в которой он будет находиться. ОК.

Создание нового проекта (выбираем AS3 Project)

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

. bin — в ней расположены исполняемые файлы проекта;
. lib — библиотеки;
. src — файлы с исходным кодом. По умолчанию дается заготовка Main.as.

Теперь просто нажмем F5 (или кнопку Test Project на панели быстрого доступа). В результате приложение запустится на компиляцию и исполнение, после чего появится пустующее окно Flash Player, а в папке bin — новый файл с именем проекта и расширением swf.

Окно свойств проекта

Теперь самое время перейти к свойствам проекта. Они доступны как из главного меню (Project -> Properties), так и через контекстное окно, которое появляется по нажатию правой кнопкой мыши над проектом в менеджере.

Здесь вы можете выбрать версию Flash Player, настроить размер Flash- приложения, цвет фона, частоту смены кадров, поменять SDK и так далее.

Файл Main.as

Теперь перейдем к файлу Main.as и рассмотрим его «внутренности»:

Интерфейс FlashDevelop

package
{
import flash.display.Sprite;
import flash.events.Event;
//
public class Main extends Sprite
{
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
//
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
}
}
}


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

Итак, самым интересным в сгенерированном коде является слово package («пакет»). Для простоты объяснения скажем, что это по существу сборка, включающая в себя классы и другие элементы программы, которые мы создаем или импортируем для конкретного случая. Основное отличие третьей версии ActionScript от второй состоит в том, что пакеты нужно указывать явно, и при этом все подразумевает определенную иерархию — само имя пакета становится частью имен тех классов, которые в нем расположены. Например, класс Cats, размещенный в пакете animals, получит имя animals.Cats. Чуть забегая вперед, скажем, что в силу требований, налагаемых компилятором языка ActionScript, исходный файл, содержащий класс (или другое описание) внутри пакета, должен размещаться в структуре папок, соответствующей имени пакета. Для приведенного примера с котами и животными .as- файл, содержащий пакет animals.Cats, должен размещаться в папке Cats, вложенной в папку animals.

Если имя пакета не указано (как в нашем случае), класс создается по умолчанию в пакете верхнего уровня.

В первых строках нашего пакета мы импортируем два класса из других пакетов, а именно, flash.display и flash.events (об этом чуть позже). Затем мы описываем основной класс Main, который расширяет класс Sprite. Далее в коде мы видим открытую функцию, одноименную с названием класса — она является конструктором, то есть выполняется автоматически при создании экземпляра класса в момент загрузки swf-файла в Flash Player. Теперь подробнее.

flash.display.Sprite

Нужно сказать, что основной класс практически всех программ на ActionScript должен расширять либо класс flash.display.Sprite, либо класс flash.display.MovieClip. И Sprite, и MovieClip представляют собой контейнеры для графического содержимого, отображаемого на экране. Оба являются потомками такого базового центрального для ActionScript класса, как DisplayObject, который отвечает за список отображения, но при этом не предназначен для создания экземпляров напрямую, а вся функциональность реализуется на уровне его подклассов.

Вариант MovieClip используется большей частью в среде разработки Adobe Flash IDE и используется при программировании в рамках FLA-файлов. В рамках Flex-проектов обычно используют Sprite.

flash.events.Event

Что касается класса flash.events.Event, то в данном случае в наш пакет автоматически включается возможность «прослушивания» событий, оно будет вызываться с помощью метода класса Event — addEventListener() и убираться с помощью removeEventListener(). Нужно сказать, что во второй версии ActionScript программистами часто используется внешний класс EventDispatcher, в AS3 — это фактически его аналог, причем именно он и стал базовым фактически для всех интерактивных объектов.

Список отображения

При открытии нового SWF-файла среда выполнения Flash создает экземпляр основного класса этого файла и добавляет созданный экземпляр в иерархический список объектов, которые отображаются в данный момент на экране. Тут важно отметить словосочетание «список отображения». Он формируется в рамках базового контейнера, к которому в качестве дочерних элементов могут добавляться любые элементы, которые необходимо отобразить.

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

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

Говоря еще проще: когда пустая среда Flash открывает новый SWF-файл, она находит основной класс этого SWF-файла, создает экземпляр данного класса и добавляет созданный экземпляр в список отображения в качестве первого ребенка экземпляра класса Stage. Часто основной класс первого загружаемого SWF-файла в среде исполнения Flash называют «владельцем сцены».

В AS3 обращение к экземпляру класса Stage происходит не напрямую, а осуществляется через некоторый объект в списке отображения с помощью переменной экземпляра stage класса DisplayObject (потомками которого также являются описанные нами выше Sprite и MovieClip).

Если на данном этапе вы что-то не очень поняли, все станет более понятно на практике.

Что прописано в конструкторе Main()?

В случае приведенного кода функции Main() прописано следующее условие: если элемент находится в списке отображения, то вызывается функция init(), которая убирает прослушивание события добавления в список отображения (строка removeEventListener(Event.ADDED_TO_STAGE, init);), в ином случае это прослушивание добавляется — (строка addEventListener(Event.ADDED_TO_STAGE, init);).

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

Но, раз в данном случае мы столкнулись именно с таким вариантом, имело смысл объяснить и сопутствующие темы.

Добавляем код. Программа «Hello, world!»

Как видите, тут в процессе изучения одно обязательно цепляет другое, поэтому если мы начнем писать приложение «Hello, world!», то сразу же внедримся в довольно обширную тему создания текстовых полей.

Hello, world!

Но пока нам нужно продемонстрировать на общем примере, как можно производить добавления в список отображения. Поэтому поступим просто. Итак, для облегчения читабельности строки с Events мы выбросим из исходного файла, равно как и импорт класса Event. В результате у нас останется только одна функция-конструтор Main().

Теперь преобразуем код до следующего:

Hello, world! через контейнер

package
{
import flash.display.Sprite;
import flash.text.TextField;
public class Main extends Sprite
{
public function Main():void
{
var hello:TextField = new TextField;
hello.border = true;
hello.text = "Hello, world!";
addChild (hello);
}
}
}

Что мы здесь сделали? Перво-наперво для работы с текстом мы импортировали соответствующий класс TextField, отвечающий за такие объекты, как текстовые поля. Затем в рамках функции Main мы создали новую переменную hello экземпляра класса TextField, после указали некоторые настройки для нее, в данном случае отобразили в рамке (hello.border=true;), а также указали значение hello.text = «Hello, world!». Затем с помощью ключевой для AS3 функции addChild() мы добавили элемент в список отображения. В результате все необходимое отобразилось на экране.

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

Список отображения формируется путем реализации связей родителей и потомков

Пример очень прост, поэтому для улучшения понимания давайте его немного расширим.

package
{
import flash.display.Sprite;
import flash.text.TextField;
public class Main extends Sprite
{
public function Main():void
{
var s:Sprite = new Sprite();
s.x = 100;
s.y = 100;
var hello:TextField = new TextField;
hello.border = true;
hello.text = "Hello, world!";
s.addChild (hello);
addChild(s);
}
}
}


Итак, в данном случае мы пошли более сложным путем, а именно создали контейнер s, указав его координаты и поместив в него наш текстовый элемент, а потом (тут внимательно) добавили этот контейнер в основной список отображения. У нас получилась следующая иерархическая цепочка отображения: stage <- Main <- s <- hello.

В рамках использования addChild() или addChildAt() следует понимать, что мы работаем с контейнерами, а визуализация происходит в том случае, если сам контейнер находится в списке отображения и коммутируется по родственным связям с уровнем stage, а если точнее, основного класса, который к тому привязан. Если вы уберете из кода последнюю строку (addChild(s);), то текстовое поле показываться не будет, потому как отсутствует вход в список отображения — нет связи с основным предком.

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

Программа №2. Математическая

В данном случае имеет смысл порисовать, что актуально для тех, кто программировал на второй версии языка. В качестве примера преобразуем код из некогда понравившейся очень многим читателям статьи «Популярно об ИИ. Муар», который выводит линии с небольшим отклонением, а в результате их пересечения получается замысловатый рисунок.

Итак, убираем импорт класса TextField, очищаем функцию Main() и вписываем в нее следующие строки:

graphics.lineStyle(1,0,1);
var i:int = 0; var y1:int = 0; var y2:int = 50;
while(i<80) {
y1 += 4;
y2 += 6;
graphics.moveTo(20, y1);
graphics.lineTo(480, y2);
graphics.moveTo(20, y2);
graphics.lineTo(480, y1);
i++;}


Как можно увидеть, при сравнении с программированием в ActionScript2 в третьей версии языка все делается по-новому, а именно: для рисования вызывается специальный класс Graphics, переменные задаются не динамически, появились их новые типы (Number подразумевает числа с плавающей запятой, а для целых предусмотрен Int). В остальном все похоже на С++-подобные языки. Поскольку рисование мы производили прямо в функции Main(), никаких телодвижений в области добавления в список отображения не требуется.

Результат примера с муаром

Подытожим

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

Кристофер http://itcs.3dn.ru


Компьютерная газета. Статья была опубликована в номере 42 за 2011 год в рубрике программирование

©1997-2024 Компьютерная газета