Macromedia Flash Professional 8. Графика и анимация

Дронов В. А.

Часть IV

Интерактивность

 

 

Глава 18

Основы программирования во Flash

 

Вот мы и добрались до программирования. Путь был долог и тяжел, но мы его преодолели, расправившись по дороге со статичной и анимированной графикой, импортированным видео и звуком. Перед нами высятся неприступные стены и грозные башни крепости под названием ActionScript. Могучие воины-действия натачивают мечи, а грозные маги-объекты извлекают из тайников древние артефакты… Однако пора заканчивать со стратегическими играми!

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

Сценарии Flash пишутся на языке программирования ActionScript, разработанном в фирме Macromedia специально для пакета Macromedia Flash. Этот язык очень прост в освоении и, вместе с тем, имеет достаточно средств для того, чтобы добавить фильмам Flash "жизни". На нем можно даже писать настоящие программы — так называемые Flash-приложения. И те из вас, кто продолжит изучение Flash 8 по его интерактивной справке или другим книгам, смогут стать настоящими Flash-программистами.

С помощью сценариев с фильмом и его элементами можно сделать все, что душе угодно. Например, можно остановить воспроизведение на каком-то кадре, а продолжить только после нажатия кнопки. Можно заставить фрагмент изображения двигаться по рабочему листу, не пользуясь стандартными средствами создания анимации, описанными в части IIIэтой книги. Можно заставить Flash открыть при щелчке на кнопке какую-либо Web-страницу. Можно… Да много чего можно сделать с помощью сценариев!

Начнем мы, как уже повелось, с теории. Нам нужно поближе познакомиться со сценариями и выяснить, как (или, точнее — когда) они работают. А заодно познакомиться с понятием события.

 

Как работают сценарии. События

Любой сценарий, который мы создаем в документе Flash, должен быть привязан к какому-то его элементу. Привязать сценарий во Flash можно:

□ к кадру анимации (внешней или внутренней, принадлежащей какому-либо образцу);

□ к клипу (в смысле — к экземпляру образца-клипа). О клипах и их создании см. главу 8;

□ к кнопке (к экземпляру образца-кнопки). О кнопках будет рассказано далее в этой главе.

Чтобы привязать к элементу изображения, нужно сначала выделить этот элемент. Далее мы просто открываем панель Actions и пишем в ней текст (или, как говорят профессиональные программисты, — код) сценария. Так, если был выделен кадр анимации, то написанный в панели Actions сценарий будет привязан к нему. Если же был выделен элемент, к которому нельзя привязать сценарий (например, "обычная" графика или экземпляр графического образца), панель Action будет недоступна.

Все сценарии Flash, привязанные к кнопке или клипу, выполняются в ответ на какое-либо событие, произошедшее в фильме Flash или операционной системе. Таким событием может быть щелчок на кнопке, "касание" мышью клипа и пр.; набор событий, к которым можно привязать сценарий, весьма обширен. Сценарии, привязанные к событиям, называются также обработчиками событий.

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

А теперь давайте выясним, как написать сценарий и привязать его к нужному событию нужного элемента документа Flash. Первый наш сценарий будет привязан к кадру фильма; заодно мы познакомимся с панелью Actions и научимся с ней работать. А потом перейдем к более сложным случаям — привязке сценариев к клипам и кнопкам. Ну и, конечно, узнаем, как создаются эти самые кнопки.

 

Привязка сценариев к кадрам анимации

 

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

На заметку

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

Этот небольшой сценарий будет выглядеть вот так:

gotoAndPlay(1);

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

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

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

В совокупности действие gotoAndPlay с параметром составляют выражение — минимальную единицу сценария ActionScript. Символ "точка с запятой" служит признаком конца выражения ActionScript и является обязательным.

Наш первый сценарий очень короток — в нем всего одно выражение. Сложные же сценарии могут содержать тысячи, а то и десятки тысяч выражений.

 

Знакомство с панелью Actions

Теперь нам осталось привязать наш сценарий к кадру. А значит, нам понадобится панель Actions. Чтобы вывести ее на экран, нужно:

□ либо включить пункт-выключатель Actions меню Window;

□ нажать клавишу ;

□ нажать кнопку, расположенную в правой части панели Properties:

Панель Actions показана на рис. 18.1. Она разделена на три части, которые мы сейчас рассмотрим.

В левой части панели Actions находится большой иерархический список доступных в языке ActionScript команд (действий, операторов, методов и пр.; с ними мы познакомимся в главе 19), которые мы можем использовать в своих сценариях. Таких команд очень много — так много, что они разбиты на несколько групп, и каждой такой группе соответствует определенное "дерево" иерархического списка. Если в сценарии нельзя использовать какую-либо команду, соответствующий ей пункт списка показан серым цветом и недоступен для выбора.

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

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

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

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

Или выбрать в дополнительном меню панели пункт Help. Также они могут щелкнуть по нужному пункту иерархического списка команд правой кнопкой мыши и выбрать в появившемся на экране контекстном меню пункт View Help. После этого на экране появится панель Help (см. рис. 2.24) с текстом справки по выбранной команде.

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

Кроме того, толстой серой линией отделены друг от друга оба иерархических списка, расположенные в левой части панели. При двойном щелчке на линии или при нажатии расположенной на ней кнопки с изображением стрелки будет убран верхний список (список доступных команд).

 

Написание сценария

Итак, с панелью Actions мы вкратце познакомились. Конечно, полностью ее возможности (кстати, весьма широкие) мы не рассмотрели, но сейчас нам важнее написать наш первый сценарий, чем выяснять, чем богата эта панель. Позже мы займемся ей более подробно.

Выше уже говорилось, что для перемещения бегунка на другой кадр нужно использовать действие gotoAndPiay. Все действия находятся в "дереве" Global Functions иерархического списка доступных команд (см. рис. 18.1). В этом "дереве" нам нужно раскрыть "ветвь" Timeline Control (в ней содержатся действия, управляющие воспроизведением анимации) и найти пункт gotoAndPiay, "отвечающий" за одноименное действие. Теперь нам нужно добавить это действие в код нашего сценария, который пока что пуст.

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

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

□ дважды щелкнуть на пункте списка;

□ выбрать пункт Add to Script в контекстном меню выбранного пункта;

□ нажать расположенную над областью редактирования кода кнопку со знаком "плюс", раскрытое меню которой показано на рис. 18.2, "проследовать" по иерархии подменю и выбрать соответствующий пункт;

□ нажать комбинацию клавиш, соответствующую требуемому пункту упомянутого выше меню (рис. 18.2).

О комбинациях клавиш, служащих для добавления в сценарий команд языка ActionScript, нужно рассказать подробнее. Эти комбинации состоят из трех клавиш: двух алфавитно-цифровых и клавиши . Нажимать их нужно так: сначала — клавишу , затем — первую клавишу, потом — вторую. И еще: перед тем как пользоваться этими комбинациями, необходимо переключиться в область редактирования кода сценария — в обоих иерархических списках панели Actions эти комбинации не действуют.

Комбинации клавиш — очень полезная вещь. Только по умолчанию они почему-то не отображаются в иерархическом списке доступных команд — наверно, разработчикам Flash это показалось излишним. Чтобы все-таки заставить Flash отображать эти комбинации прямо в этом списке, достаточно включить пункт-выключатель Esc Shortcut Keys в дополнительном меню панели Actions.

Итак, мы выбрали действие gotoAndPlay и добавили его в код сценария одним из описанных выше способов. Это действие тотчас появится в области редактирования кода:

gotoAndPlay()

Осталось ввести значение параметра действия gotoAndPlay, равное 1, возможно, поставить точку с запятой — и первый наш сценарий готов. Он будет таким:

gotoAndPlay(1);

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

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

На этом создание нашего первого сценария можно считать законченным. Проверим его в действии.

 

Воспроизведение фильмов, кадры которых содержат сценарии

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

Если мы сейчас начнем воспроизведение нашего фильма, выбрав пункт Play меню Control или нажав клавишу , то Flash корректно обработает наш сценарий и выполнит переход на первый кадр сцены Фильм по достижении ее последнего кадра. Если же он этого не сделает, нужно проверить, включен ли пункт-выключатель Enable Simple Frame Actions меню Control. Как раз этот пункт при включении предписывает Flash выполнять сценарии, привязанные к кадрам.

 

Привязка сценариев к клипам

Привязать сценарий к кадру, как мы только что убедились, несложно. А как насчет клипа?

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

Для экспериментов возьмем фильм, в котором демонстрировались возможности составной анимации (см. главу 13). (Помните этот фильм: прямоугольник, кувыркаясь, летит по рабочему листу?) Загрузим содержащий его документ. И выполним подготовительные действия.

1. Преобразуем экземпляр графического образца в экземпляр-клип, если не сделали этого раньше. Для чего выберем в раскрывающемся списке, расположенном в верхнем левом углу панели Properties, пункт Movie Clip.

2. Дадим клипу имя, например, clip.

Теперь все готово для написания сценария.

Давайте сделаем так, чтобы при щелчке мышью на вложенном клипе он останавливал свое воспроизведение, переставая крутиться. Конечно, пользы от такой интерактивности никакой, но, по крайней мере, это будет наш первый опыт привязки сценария к клипу. Мы ведь пока только учимся писать сценарии…

Итак, к делу! Выделим клип clip на рабочем листе. И вспомним то, что говорилось в начале этой главы о событиях.

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

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

Полный "шаблон" для написания сценария-обработчика события будет иметь такой вид:

onClipEvent (<Обозначение события>)

{

<Код сценария-обработчика>

}

Первая строка этого "шаблона" задает событие, на которое "откликается" обработчик, и называется заголовком. Сам же код обработчика помещается в фигурных скобках после заголовка и называется телом.

Давайте же, поглядывая на приведенный выше "шаблон", напишем свой сценарий. Он будет таким:

onClipEvent(mouseDown)

{

stop();

}

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

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

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

Выше говорилось, что Flash при воспроизведении фильмов может выполнять простейшие сценарии, привязанные к кадрам. Сейчас же мы привязали сценарий к клипу, а не к кадру, а такие сценарии Flash выполнить не сможет. Поэтому нам придется выбрать пункт Test Movie меню Control или нажать комбинацию клавиш < Ctrl>+< Enter>, чтобы запустить воспроизведение фильма в отдельном окне.

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

Ура, наш первый обработчик события работает! Давайте его немного усложним. Снова выделим клип clip, откроем панели Actions и допишем в сценарий еще одно выражение. Наш сценарий примет такой вид (добавленное выражение выделено полужирным шрифтом):

onClipEvent(mouseDown)

{

stop();

_parent.stop();

Специальная команда языка ActionScript _parent обозначает клип, в который вложен клип, к которому привязан этот сценарий — в нашем случае это будет основной фильм. (Такие команды, кстати, называются ключевыми словами.) Ну, а записанное после этого слова и отделенное от него точкой действие stop нам уже знакомо.

Что же мы получим в результате? А вот что. Проигрыватель Flash прочитает сначала ключевое слово _parent, а потом — действие stop. И поймет, что действие stop нужно распространить на основной фильм — ведь именно в него вложен клип clip. Так что добавленное нами выражение остановит внешнюю анимацию.

 

Привязка сценариев к кнопкам

 

Кнопки Flash мы пока еще подробно не рассматривали, не считая краткого упоминания в главе 8. Настала пора поговорить о них подробно.

Кнопки (или экземпляры образцов-кнопок) Flash ведут себя подобно обычным кнопкам, которые мы встречаем практически во всех приложениях Windows. Они могут быть нажаты, в результате чего всегда выполняется какой-либо сценарий.

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

 

Создание кнопок

Прежде чем привязывать к кнопке сценарий, ее нужно создать. Займемся этим.

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

Сначала нам нужно создать образец-кнопку. Делается это уже знакомым нам из главы 8 способом. Выберем пункт New Symbol меню Insert, в поле Name диалогового окна Create New Symbol (см. рис. 8.2) введем имя создаваемого образца-кнопки (дадим ему имя Кнопка), включим переключатель Button в группе Behavior и нажмем кнопку ОК. После этого Flash откроет вновь созданный, пока еще "пустой" образец в режиме правки. Нам останется только нарисовать нашу кнопку.

Но не будем спешить это делать. Посмотрим лучше на временную шкалу (рис. 18.4). Она содержит всего четыре позиции, и весьма странных — все они имеют имена: Up, Over, Down и Hit. В позиции Up уже создан ключевой кадр.

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

□ изображение, находящееся в кадре Up, выводится, когда кнопка не нажата и курсор мыши не установлен над ней;

□ изображение, находящееся в кадре Over, выводится, когда курсор мыши установлен над кнопкой, но сама кнопка не нажата;

□ изображение, находящееся в кадре Down, выводится в тот момент, когда пользователь нажимает кнопку;

□ изображение, находящееся в кадре Hit, задает область, которая будет откликаться на касания и щелчки мышью ("горячую область" кнопки). Это изображение никогда не выводится на экран.

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

□ Если отсутствует кадр Hit, "горячую область" определяет изображение в кадре Up.

□ Если отсутствует кадр Down, для отображения нажатой кнопки Flash возьмет изображение из кадра Over.

□ Если отсутствует кадр Over, для отображения кнопки, которой "коснулся" курсор мыши, Flash позаимствует изображение из кадра Up.

Кнопки Flash имеют еще одну интересную особенность. Дело в том, что "горячая" область кнопки совсем не обязательно должна совпадать с самой кнопкой. Так, иная кнопка может сработать, если пользователь щелкнет совсем в другом месте рабочего листа. Это обстоятельство позволяет создавать весьма забавные и полезные вещи вроде подсказок, "всплывающих" при наведении мыши на какой-либо фрагмент изображения, и пр.

Но давайте все-таки нарисуем нашу кнопку. Не станем особенно мудрить — нарисуем в кадре Up обычный синий прямоугольник. На первый раз этого будет достаточно.

Следующий шаг — рисование изображения в кадре Over. Пусть это будет красный прямоугольник. Создадим в делении Over новый ключевой кадр; Flash автоматически поместит туда изображение из кадра up, и нам останется только перекрасить его в красный цвет.

Нарисуем содержимое остальных двух кадров кнопки. В кадре Down прямоугольник пусть будет темно-синим. А цвет изображения в кадре Hit роли не играет.

Все — образец-кнопка готов. Вернемся в режим правки фильма и откроем панель Library. Создадим новый слой и назовем его Кнопка — именно в него мы и поместим нашу кнопку, иначе анимация в первом слое окажется "оборванной". Найдем в списке образцов только что созданную нами кнопку и поместим в нижний правый угол рабочего листа ее экземпляр. И, наконец, проверим ее в действии.

 

Воспроизведение фильмов, содержащих кнопки

Воспроизведение фильмов, содержащих кнопки, также имеет некоторые особенности. Flash способен сделать так, что мы сможем нажимать кнопки прямо во время работы над фильмом (конечно, привязанные к ним сценарии работать не будут). Это поможет проверить правильность всех наших действий.

Чтобы задействовать режим обработки кнопок на рабочем листе, нам нужно будет включить пункт-выключатель Enable Simple Buttons меню Control. Также можно нажать комбинацию клавиш ++. После этого,

если мы поместим курсор мыши над кнопкой, она сменит свой цвет на красный. Мы даже сможем ее нажать (правда, привязанный к кнопке сценарий в этом случае не будет выполнен).

Единственный недостаток такой кнопки: мы не сможем ее выделить. Для этого нам придется отключить пункт-переключатель Enable Simple Buttons меню Control.

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

 

Добавление звуков к кнопкам

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

Прежде всего, импортируем требуемые звуки в библиотеку. (О том, как это делается, было подробно рассказано в главе 17.) Дадим получившимся в результате импорта образцам-звукам "говорящие" имена, например: касание и нажатие. Все — можно приступать к "озвучке" кнопки.

Откроем нужный образец-кнопку в режиме правки. Создадим новый слой для звуков и назовем его Звук-касание. После этого выделим деление over временной шкалы, создадим в нем ключевой кадр и поместим на рабочий лист экземпляр образца-звука Касание. Результат этих действий показан на рис. 18.5.

Чтобы привязать звук к состоянию Down кнопки, нам нужно будет создать еще один слой — Звук-нажатие. После этого останется только создать ключевой кадр в делении Down и поместить в него звук Нажатие.

Теперь можно вернуться в основной фильм и проверить "озвученную" кнопку в действии. Проще всего это сделать, запустив воспроизведение фильма в отдельном окне.

 

Написание сценариев, привязанных к кнопкам

Уф! Наконец-то кнопка создана. Теперь можно заняться собственно привязкой к ней сценария.

Сценарии привязываются к кнопке точно так же, как и к клипу. Мы выделяем на рабочем листе нужную кнопку, даем ей имя (скажем, button), воспользовавшись панелью Properties, вызываем на экран панель Actions и пишем в ее области редактирования код нужного сценария. Различия имеются только в наименовании событий и синтаксисе заголовков их обработчиков.

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

on(< Обозначение события>)

{

<Код сценария-обработчика>

}

Обратим внимание, что вместо действия onclipEvent в этом случае используется действие on. Это первое отличие. Второе же отличие заключается в том, что для обозначения события нажатия кнопки нам будет нужно использовать Слово press, а не mouseDown.

Учитывая сказанное, напишем сценарий для кнопки. Он будет таким:

on (press)

{

stop();

}

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

Введем этот сценарий в область редактирования кода панели Actions и запустим воспроизведение фильма в отдельном окне. После этого щелкнем по кнопке, и вся анимация — и внешняя, и внутренняя — остановится.

 

Работа с панелью Actions

С панелью Actions мы уже знакомы. (Еще бы — сколько сценариев с ее помощью мы уже написали!.. Целых четыре!) Давайте посмотрим, что она нам еще может предложить, продолжим знакомство, так сказать.

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

Кроме того, панель Actions предоставляет нам дополнительные инструменты, которые сильно облегчат наш труд. Рассмотрим самые полезные из них.

Подсказка по коду. Когда мы открываем круглую скобку, готовясь ввести значение параметра какого-либо действия (например, gotoAndPlay), чуть ниже текстового курсора появляется небольшое светло-желтое окошко с текстом, описывающим назначение этого параметра (рис. 18.6). После того как мы введем значение этого параметра и поставим запятую, подсказка выдаст описание следующего параметра, и т. д. Щелкая на небольших стрелках, находящихся в окне подсказки и направленным вправо и влево, можно просмотреть описания соответственно следующего и предыдущего параметров.

Подсказки-списки. Если мы откроем скобку, чтобы задать параметр, значения которого должны выбираться из ограниченного списка, на экране появится этот самый список со значениями (рис. 18.7). Нам останется только выбрать в списке нужное значение либо щелчком мыши, либо выделив его клавишами-стрелками и нажав клавишу .

Любую из этих подсказок можно вызвать на экран, поставив в нужное место кода текстовый курсор и нажав кнопку, расположенную над областью редактирования кода:

Также можно выбрать пункт Show Code Hint в дополнительном меню панели или, что проще всего при работе с клавиатурой, нажать комбинацию клавиш < Ctrl>+<пробел>.

Автоматическое создание отступов при вводе строк кода. (Отступы очень часто применяются, например, для выделения тела обработчика события.) Если мы ввели строку с отступом от ее начала, то при нажатии клавиши новая строка будет иметь такой же отступ. Отступы формируются также, если предыдущая строка заканчивается круглой или фигурной скобкой.

Можно установить отступ вручную, для чего достаточно целиком выделить нужные строки кода и нажать клавишу <Таb>. Чтобы убрать отступ, нужно также выделить строки и нажать комбинацию клавиш +.

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

Также можно выбрать пункт Check Syntax в дополнительном меню панели или нажать комбинацию клавиш +. Flash проверит введенный нами код на правильность и выведет окно-предупреждение с текстом "The script contains no errors" (если сценарий не содержит ошибок) или "This script contains errors. The errors encountered are listed in Output Panel" (если сценарий содержит ошибки).

Если сценарий содержит ошибки, Flash также выведет на экран небольшую панель Output, в которой будут приведены описания всех найденных ошибок (рис. 18.8). Правда, эти описания будут даны по-английски…

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

Для выполнения поиска подстроки нужно нажать кнопку, расположенную над областью редактирования кода:

Можно также выбрать в дополнительном меню панели пункт Find and Replace или нажать комбинацию клавиш +. В результате этого на экране появится диалоговое окно Find and Replace (рис. 18.9).

В поле ввода Find what зададим искомую подстроку, включим флажок Match case, если желаем, чтобы Flash учитывал при поиске регистр символов, и нажмем кнопку Find Next. Flash выделит первую строку кода, в которой имеется заданная нами подстрока. Если подстрока так и не будет найдена, Flash выведет окно-предупреждение с текстом "Cannot find the string "<Искомая подстрока>"".

Чтобы продолжить поиск введенной подстроки далее по тексту сценария, мы снова нажмем кнопку Find Next диалогового окна Find. Если мы уже закрыли это окно (для чего достаточно нажать кнопку Close), то выберем в дополнительном меню панели пункт Find Again или нажмем клавишу .

Для выполнения замены искомой подстроки на другую служит все то же окно Find and Replace. В этом случае после задания искомой подстроки нужно будет ввести в поле Replace with подстроку, которая заменит искомую. Опять же, можно установить флажок Match case, чтобы Flash учитывал при поиске регистр символов. Замена запускается нажатием кнопки Find Next. Flash выделит первую строку кода, в которой встретилась искомая подстрока. После этого мы можем нажать кнопку Replace, чтобы выполнить замену. Для продолжения поиска нужно снова нажать кнопку Find Next.

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

Автоматическая нумерация строк сценария. Чтобы воспользоваться этим средством, достаточно включить пункт-выключатель Line Numbers в дополнительном меню панели или нажать комбинацию клавиш + ++.

Быстрый переход на строку кода с заданным номером. Выбираем пункт Go to Line дополнительного меню панели или нажимаем комбинацию клавиш +, вводим номер нужной строки в поле ввода Line number диалогового окна Go to Line (рис. 18.10) и нажимаем кнопку ОК:

Автоматический перенос слишком длинных строк. От него можно избавиться, отключив пункт-выключатель Word Wrap дополнительного меню панели или нажав комбинацию клавиш ++. Правда, в этом случае нам придется часто пользоваться горизонтальной полосой прокрутки, чтобы просмотреть слишком длинные строки кода.

Печать всех сценариев, созданных в документе. Выбираем пункт Print дополнительного меню панели. На экране появится стандартное диалоговое окно задания параметров печати Windows; задаем эти параметры и нажимаем кнопку ОК.

 

Поведения Flash и их использование

Специально для начинающих программистов Flash представляет набор так называемых поведений (behaviors). Это набор сценариев ActionScript, которые мы можем привязать к кадру, клипу или кнопке без необходимости набирать их вручную в панели Actions. Таких поведений в составе Flash поставляется довольно много; они служат для управления анимацией, клипами, звуком и пр.

Работа с поведениями — создание, правка и удаление — выполняется с помощью панели Behaviors (рис. 18.11). Чтобы вывести эту панель на экран, нужно включить пункт-выключатель Behaviors меню Window или нажать комбинацию клавиш +.

Большую часть этой панели занимает список поведений, уже привязанных к выделенному элементу фильма: кадру, клипу или кнопке. (На рис. 18.11 этот список пуст.) Он организован в виде таблицы из двух колонок: Event (событие, которое обрабатывает поведение) и Action (поведение, выполняемое в ответ на событие).

Чтобы создать поведение, привязанное к какому-либо элементу фильма, нужно выделить этот элемент (его имя, равно как и имя образца, на основе которого он был создан, появятся над списком поведений) и нажать на кнопку с изображением знака "плюс" панели Behaviors. На экране появится небольшое меню (рис. 18.12), содержащее все доступные поведения, сгруппированные в категории. Категории представляют собой подменю, а сами поведения — пункты этих подменю.

После выбора пункта, соответствующего нужному поведению, на экране появится диалоговое окно, где нужно будет задать параметры этого поведения. Поведение будет создано после нажатия кнопки ОК этого окна. А в списке панели Behaviors появится соответствующая этому поведению строка.

Если поведение было привязано к клипу или кнопке, нужно будет задать событие, в ответ на которое будет выполняться сценарий этого поведения. Для этого достаточно выбрать нужную строку в списке панели Behaviors и щелкнуть внутри колонки Event этой строки. После этого там появится небольшой раскрывающийся список (рис. 18.13), в котором и выбирается нужное событие.

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

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

 

Что дальше?

Ну что ж, мы сделали самый первый шаг в мире Flash-программирования. Мы усвоили новые термины, изучили новые инструменты и были потрясены открывшимися перед нами новыми возможностями. И мы написали целых четыре сценария! Хоть они и очень просты, но ведь это все-таки наш первый шаг…

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

 

Глава 19

Язык ActionScript

 

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

Эта глава действительно велика. Так что не будем тратить время зря.

 

Начала языка ActionScript

 

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

 

Основные понятия ActionScript

Сценарий — это последовательный набор выражений, которые могут содержать действия — команды, воздействующие непосредственно на фильм. Также в выражениях могут быть ключевые слова — особые слова языка ActionScript, имеющие специальное значение, но не воздействующие на фильм непосредственно. Каждое выражение ActionScript должно завершаться знаком "точка с запятой". Все это нам уже знакомо из главы 18.

Вот типичный пример сценария:

on (press) {

stop ();

}

Это обработчик события press, которое возникает в кнопке при щелчке по ней. Он останавливает воспроизведение анимации.

А вот еще один обработчик события:

onClipEvent(mouseDown) {

b = а + 2;

gotoAndPlay(b);

}

Он выполняется в ответ на событие mouseDown, возникающее при щелчке мышью на клипе. Его второе выражение, содержащее действие gotoAndPlay, нам уже знакомо. (Правда, вместо номера кадра в качестве параметра действию передается нечто непонятное, но об этом потом.) Первое же выражение нам что-то напоминает… Математическая формула?

Да, это математическая формула, записанная на языке ActionScript в вице выражения. Подобные выражения называются математическими выражениями. Выражение b = а + 2, как можно предположить, вычисляет некое значение. Давайте рассмотрим его подробнее.

Очевидно, что данное выражение складывает две величины — об этом говорит знак +. Этим знаком обозначается оператор арифметического сложения ActionScript, выполняющий сложение двух величин. Оператор — это команда, выполняющая действия над данными сценария, а не над элементами фильма. Забегая немного вперед, скажем, что в ActionScript существуют также операторы арифметического вычитания, умножения и деления, обозначаемые соответственно знаками —, * и /.

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

Первый же операнд в выражении какой-то непонятный — он обозначен буквой а. Что это такое? А это переменная — ячейка памяти, в которую можно на время поместить какое-либо значение, чтобы сохранить его до лучших времен. (Поэтому она и называется переменной, в отличие от константы.) Каждая переменная должна иметь уникальное имя.

Итак, что же делает описанное выражение? Оно берет из переменной а значение первого операнда, складывает его с константой 2 (второй операнд), а результат помещает в переменную b Помещение результата в переменную b выполняется с помощью оператора присваивания, обозначаемого символом =.

Вот еще один пример арифметического выражения, на этот раз более сложного:

у = yl * у2 + х1 * х2;

Здесь операторы выполняются в следующем порядке:

1. Значение переменной y1 умножается на значение переменной у2.

2. Перемножаются значения переменных x1 и х2.

3. Полученные на шагах 1 и 2 произведения складываются.

4. Полученная сумма присваивается переменной у.

Но почему на шаге 2 выполняется умножение x1 на х2, а не сложение произведения у1 и у2 с x1. Дело в том, что каждый оператор имеет приоритет — своего рода номер в очереди их выполнения. Так вот, оператор умножения имеет более высокий приоритет, чем оператор сложения, поэтому умножение всегда выполняется перед сложением.

А вот еще одно выражение:

х = х + 3;

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

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

 

Данные ActionScript. Типы данных

Любая программа при своей работе оперирует некими данными. Такими данными могут быть координаты клипа на рабочем листе, номер кадра, имя и пароль пользователя, цена какого-нибудь товара в интернет-магазине, величина атмосферного давления и пр. Конечно, не составляют исключения и сценарии ActionScript; мы сами использовали номер кадра, когда писали наши первые сценарии (см. главу 18).

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

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

"Flash 8"

"1234567"

'Строковые данные — это последовательности символов.'

Строки могут иметь любую длину (определяемую количеством составляющих их символов), ограниченную лишь объемом свободной памяти компьютера. Разумеется, теоретически существует предел в 2 Гбайт, но вряд ли в нашей практике встретятся столь длинные строки.

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

Набор всех доступных символов вместе с соответствующими им кодами называется кодировкой. Flash 8 для хранения строк использует кодировку Unicode, в которой каждый символ представлен двумя байтами (можно кодировать до 65 535 символов). Кодировка Unicode содержит практически все символы практически всех языков мира; это позволяет использовать в документах Flash тексты на любых языках мира.

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

Числовые данные (или число) — это обычные числа, над которыми можно производить все арифметические действия, извлекать из них квадратный корень и вычислять тригонометрические функции. Числа могут быть как целыми, так и дробными; в последнем случае целая и дробная части разделяются точкой (не запятой!).

Примеры чисел:

13756

454.7873

0.5635

Для записи дробных чисел может быть использована экспоненциальная форма вида <мантисса>Е<порядок>. Вот примеры заданных таким образом чисел (в скобках дано традиционное математическое представление):

IE-5 (10 -5 )

8.546Е23 (8,546×10 23 )

Логическая величина может принимать только два значения: true и false — "истина" и "ложь", — обозначаемые соответственно ключевыми словами true и false. Логические величины часто используются в операциях сравнения (о них будет рассказано далее в этой главе).

ActionScript также поддерживает два специальных типа. Эти типы обозначают отсутствие любых данных. Тип null обозначает отсутствие каких-либо данных и обозначается ключевым словом null. А тип undefined указывает на то, что переменной не было присвоено никакое значение, и обозначается ключевым словом undefined.

Внимание!

Undefined — это не то же самое, что null !

Остальные типы данных, поддерживаемые ActionScript и не описанные здесь, мы рассмотрим позже.

 

Константы

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

26756

"Строка"

true

null

ActionScript также предоставляет несколько специальных констант, заданных ключевыми словами. Среди них, например, есть константа infinity, представляющая значение ∞, возникающее при делении на ноль. А константа — infinity представляет значение — ∞.

 

Переменные

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

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

Именование переменных

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

В имени переменной могут присутствовать латинские и русские буквы, цифры, символы $ (знак доллара) и _ (знак подчеркивания), причем первый символ имени должен быть либо буквой, либо знаком доллара или подчеркивания. Например, FrameNumber, _link, ИмяПользователя — правильные имена переменных, a 67 8vasya и имя пользователя — неправильные.

Нужно сразу сказать, что язык ActionScript чувствителен к регистру символов, которыми набраны имена переменных. Это значит, что framenumber и FrameNumber — разные переменные.

При выборе имен переменных специалисты фирмы Macromedia рекомендуют следовать одному простому правилу: имя должно быть "говорящим". Это значит, что имя должно отражать назначение переменной. Например, переменную, в которой хранится номер кадра, лучше всего назвать frameNumber — так будет сразу понятно, зачем она нужна. Но не стоит слишком усердствовать: имена типа lastVisitedFormFrameNumber очень трудно набирать. Для временных переменных (хранящих данные, необходимые в данный конкретный момент) лучше всего брать однобуквенные имена: i, a, x, y и т. п.

Объявление переменных

Перед использованием переменной в коде сценария обязательно нужно выполнить ее объявление. Для этого используется оператор объявления переменной var, после которого указывается имя переменной. Вот так:

var х;

Теперь объявленной переменной можно присвоить какое-либо значение:

х = 1234;

и использовать в сценарии:

у = х / 2 + 10;

Значение переменной также можно присвоить прямо при ее объявлении:

var х = 1234;

Нужно сказать, что объявлять переменные с помощью оператора var не обязательно. Мы можем просто присвоить переменной какие-либо значение, и Flash сам ее создаст. Просто явное объявление переменных оператором var считается хорошим стилем программирования.

Внимание!

Если обратиться к переменной, еще не получившей никакого значения, она вернет значение undefined .

Область видимости переменных

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

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

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

Такие переменные называются переменными уровня клипа. Говорят, что такие переменные "видны" только в "своем" клипе.

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

someClip.someVar = 0;

Глобальные переменные "видны" абсолютно из всех сценариев, находящихся в данном фильме. Они объявляются с помощью модификатора (особого ключевого слова, изменяющего действие какой-либо команды ActionScript) _giobal, который добавляется перед именем переменной и отделяется от него точкой:

_global.someVar = 0;

Существует еще один тип видимости переменных — локальные переменные. Мы поговорим о них, когда начнем изучение функций.

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

Давайте рассмотрим такой пример:

_global.someVar: String = "Value";

var someVar: Integer = 3;

s = someVar;

Мы объявили две переменные someVar, одну — уровня клипа, другую — глобальную, и присвоили им разные значения. Если мы теперь запросим значение переменной someVar, то переменной s будет присвоено число 3 — значение переменной someVar уровня клипа как имеющей более "узкую" область видимости. Глобальная переменная someVar будет "замаскирована".

Внимание!

Всегда проверяйте, к какой переменной вы обращаетесь. Ошибки доступа к переменным — самые трудноулавливаемые.

Но как получить значение глобальной переменной someVar? Очень просто — нужно использовать модификатор _giobal:

s = _global.someVar;

 

Операторы

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

Арифметические операторы

Арифметические операторы служат для выполнения арифметических действий над значениями констант и переменных. Все арифметические операторы, поддерживаемые ActionScript, перечислены в табл. 19.2.

Арифметические операторы делятся на две группы: унарные и бинарные. Унарные операторы выполняются над одним операндом; к ним относятся операторы смены знака, инкремента и декремента. Унарный оператор извлекает из переменной значение, изменяет его и снова помещает в ту же переменную. Приведем пример выражения с унарным оператором:

++r;

При выполнении этого выражения в переменной r окажется ее значение, увеличенное на единицу. А если записать вот так:

s = ++r;

то же значение будет помещено и в переменную s.

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

Бинарные операторы всегда имеют два операнда и помещают результат в третью переменную. Вот примеры выражений с бинарными операторами:

l = r * 3.14;

f = е / 2;

х = х + t / 3;

Внимание!

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

Оператор объединения строк

Оператор объединения строк + позволяет соединить две строки в одну. Например, сценарий:

s1 = "Flash";

s2 = "8";

s = s1 + s2;

поместит в переменную s строку "FiashS".

Операторы присваивания

Оператор простого присваивания = нам уже знаком. С его помощью переменной присваивается новое значение:

а = 2;

b = с = 3;

Второе выражение в приведенном примере выполняет присвоение значения 3 сразу двум переменным — b и с.

Кроме операторов присваивания, ActionScript поддерживает операторы сложного присваивания. Такие операторы позволяют выполнять операцию присваивания одновременно с другой операцией:

а = а + b;

а += b;

Два этих выражения эквивалентны по результату. Просто во втором был использован оператор сложного присваивания +=.

Все операторы сложного присваивания, поддерживаемые ActionScript, и их эквиваленты приведены в табл. 19.3.

Операторы сравнения

Операторы сравнения сравнивают два операнда и возвращают логическое значение. Если условие сравнения выполняется, возвращается логическое значение "истина" (true), если не выполняется — "ложь" (false). Вот примеры выражений с операторами присваивания:

а1 = 2 < 3;

a2 = -4 > 0;

а3 = r < t;

Переменная a1 получит значение true (2 меньше 3), переменная а2 — значение false (число -4 по определению не может быть больше нуля), а значение переменной а3 будет зависеть от значений переменных r и t.

Все поддерживаемые ActionScript операторы сравнения приведены в табл. 19.4.

С первыми шестью операторами сравнения все понятно. Но на двух последних операторах — "строго равно" и "строго не равно" — нужно остановиться подробнее. Это операторы так называемого строгого сравнения. Обычные операторы "равно" и "не равно", если встречают операнды разных типов, пытаются преобразовать их к одному типу (о преобразованиях типов см. далее в этой главе). Операторы строгого равенства и строгого неравенства такого преобразования не делают, а в случае несовместимости типов операндов возвращают false.

Логические операторы

Логические операторы выполняют действия над логическими значениями. Все они приведены в табл. 19.5. А в табл. 19.6 и 19.7 показаны результаты выполнения этих операторов.

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

а = (b > 0) && (с + 1! - d);

flag =! (status — 0);

Оператор typeof

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

Оператор typeof может использоваться, например, так:

status = typeof (somevar);

Здесь мы присваиваем результат выполнения оператора typeof строковой переменной status. Впоследствии он может быть использован, например, в условном выражении.

Совместимость и преобразование типов данных

И напоследок рассмотрим еще два важных вопроса: совместимость типов данных и преобразование одного типа к другому.

Что получится, если сложить два числовых значения? Правильно — еще одно числовое значение. А если сложить число и строку? Трудно сказать. Тут Flash сталкивается с проблемой несовместимости типов данных и пытается сделать эти типы совместимыми, преобразуя один из них к другому. Сначала он пытается преобразовать строку в число и, если это удается, выполняет сложение. В случае неудачи число будет преобразовано в строку, и две полученные строки будут объединены. Например, в результате выполнения операторов

var а, b, с, d, е, f;

а = 11;

b = "12";

с = а + b;

d = "Flash";

е = 8;

f = d + е;

значение переменной b при сложении с переменной а будет преобразовано в числовой тип; таким образом, переменная с будет содержать значение 23. Но так как значение переменной d не может быть преобразовано в число, значение е будет преобразовано в строку, и результат — значение f — станет равным "FlashS".

Логические величины преобразуются либо в числовые, либо в строковые, в зависимости от конкретного случая. Значение true будет преобразовано в число 1 или строку "1", а значение false — в 0 или "0".

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

Для преобразования типов данных используется следующий синтаксис:

<Переменная нужного типа> = <Ключевое слово, соответствующее этому типу>

(<Преобразуемое значение>);

Ключевые слова, соответствующие тому или иному типу данных, приведены в табл. 19.8. Да, именно эти слова возвращает оператор typeof в качестве результата. Единственное — их нужно указывать с большой буквы.

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

n = Number("2004");

Если же Flash не сможет выполнить заданное преобразование типов, будет возвращено значение null.

Приоритет операторов

Последний вопрос, который мы здесь рассмотрим, — это приоритет операторов. Как мы помним, приоритет влияет на порядок, в котором выполняются операторы в выражении.

Пусть имеется следующее выражение:

а = b + с — 10;

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

Теперь рассмотрим такое выражение:

а = b + с * 10;

А в этом случае сначала будет выполнено умножение значения с на 10, а уже потом к полученному произведению будет прибавлено значение b. Оператор умножения имеет больший приоритет, чем оператор сложения, поэтому порядок "строго слева направо" будет нарушен.

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

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

В табл. 19.9 перечислены все изученные нами операторы в порядке убывания их приоритетов. Полную таблицу приоритетов можно найти в интерактивной справке Flash.

Внимание!

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

Но что делать, если нам нужно нарушить обычный порядок выполнения операторов? Воспользуемся скобками. При такой записи заключенные в скобки операторы выполняются первыми.

а = (b + с) * 10;

В этом случае сначала будет выполнено сложение значений переменных b и с, а потом получившаяся сумма будет умножена на 10.

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

а = ((b + с) * 10 — d) /2 + 9;

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

1. Сложение b и с.

2. Умножение полученной суммы на 10.

3. Вычитание d из произведения.

4. Деление разности на 2.

5. Прибавление 9 к частному.

Если удалить скобки:

a=b+c*10-d/ 2 + 9;

то порядок выполнения операторов будет таким:

1. Умножение с и 10.

2. Деление d на 2.

3. Сложение b и произведения с и 10.

4. Вычитание из полученной суммы частного от деления d на 2.

5. Прибавление 9 к полученной разности.

Получается совсем другой результат, не так ли?

 

Комментарии

Очень часто при написании сценариев возникает потребность поместить в код ActionScript какие-либо примечания для себя или коллег по работе. Для этого используются особые выражения языка ActionScript, так называемые комментарии. Комментарии не обрабатываются Flash и исключаются из сценариев при экспорте фильма, поэтому в них можно писать все что угодно.

Для вставки комментариев в код ActionScript предусмотрены два оператора комментария: // и /*. */. Первый из них позволяет вставить в конец выражения однострочный комментарий:

// Строка комментария

а = b + с; // Это однострочный комментарий

Заметим, что комментарий ставится после точки с запятой, обозначающей конец выражения.

А оператор /*…*/ позволяет вставить в код программы комментарий любого размера:

/*

В этом выражении мы складываем содержимое двух переменных и помещаем результат в третью */

а = b + с;

 

Сложные выражения ActionScript

 

Рассмотрение основных понятий ActionScript мы закончили. Можно приступать к изучению более сложных вопросов. И начнем мы с написания так называемых сложных выражений.

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

 

Блоки

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

{

b = "12";

с = а — b;

}

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

 

Условные выражения

Условное выражение позволяет нам выполнить одно из двух входящих в него выражений в зависимости от выполнения или невыполнения какого-либо условия. Существует также другая, "вырожденная" разновидность условного выражения, содержащая только одно выражение, которое выполняется при выполнении условия и пропускается, если условие не выполнено.

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

Условное выражение имеет следующий формат:

if

( <Условие>).

<Блок "то">

else

<Блок "иначе ">

"Вырожденный" формат его выглядит так:

if ( <Условие>).

<Блок "то">

Для написания условных выражений используются особые ключевые слова if и else (в приведенных выше примерах они выделены полужирным шрифтом). Условие — это и есть логическое выражение, в соответствии с которым Flash принимает решение, какой блок выполнить. Если условие имеет значение true ("истина"), то выполняется блок "то". Если же условие имеет значение false ("ложь"), то выполняется блок "иначе" (если он присутствует в условном выражении). Если же блок "иначе" отсутствует, выполняется следующее выражение сценария.

Рассмотрим несколько примеров.

if (х == 1) {

а = "Единица";

b = 1;

}

else {

а = "Не единица";

b = 22222;

}

Здесь мы сравниваем значение переменной х с единицей и в зависимости от результатов сравнения присваиваем переменным f и h разные значение. Обратим внимание на условие — именно так записывается оператор сравнения, в скобках.

Условие может быть довольно сложным:

if ((х == 1) && (у > 10))

f = 3;

else

f = 33;

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

Если условное выражение совсем простое, мы можем записать его немного по-другому. А именно, воспользоваться условным оператором?:

<Условиe>? <Выражение "то">: <Выражение "иначе">;

Достоинство этого оператора в том, что он может быть частью выражения. Например:

f = (х == 1 && у > 10)? 3: 33;

Фактически мы записали условное выражение из предыдущего примера, но в виде обычного арифметического выражения. Компактность кода налицо. Недостаток же оператора? в том, что с его помощью можно записывать только самые простые условные выражения.

 

Выражения выбора

Выражение выбора — это фактически несколько условных выражений, объединенных в одном.

Его формат таков:

switch ( <Условиe>) {

case <Значение 1>:

<Блок 1>

[break;]

[ case   <Значение 2>:

<Блок 2>

[break;]]

<… Другие секции case>

[ default :

<Блок, исполняемый для остальных значений>]

}

В выражениях выбора используются ключевые слова switch, case и default (выделены полужирным шрифтом).

Давайте выясним, как выполняется выражение выбора. Результат вычисления условия последовательно сравнивается со значением 1, значением 2 и т. д. и, если такое сравнение увенчалось успехом, выполняется соответствующий блок кода (блок 1, блок 2 и т. д.). Если же ни одно сравнение не увенчалось успехом, выполняется блок кода, находящийся в секции default (если, конечно, она есть).

Пример использования выражения выбора:

switch (а) {

case 1:

out = "Единица";

break;

case 2:

out = "Двойка";

break;

case 3:

out = "Тройка";

break;

default:

out = "Другое число";

}

Встретив действие break, Flash прерывает выполнение блока, в котором оно присутствует, и начинает выполнение кода, следующего за выражением выбора. Если его опустить, то будет выполнен следующий блок. Так, если значение условия совпало со значением 1 и был выполнен блок 1, не содержащий действия break, будет также выполнен блок 2.

Давайте уберем все действия break в нашем примере:

switch (а) {

case 1:

out = "Единица";

case 2:

out = "Двойка";

case 3:

out = "Тройка";

default:

out = "Другое число";

}

В этом случае все блоки будут выполняться последовательно, один за другим. И переменной out всегда будет присваиваться строка "Другое число".

 

Циклы

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

ActionScript предлагает программистам несколько разновидностей циклов. Рассмотрим их.

Цикл со счетчиком

Цикл со счетчиком используется, если какой-то код нужно выполнить определенное число раз. Это наиболее часто используемый вид цикла.

Для подсчета того, сколько раз был выполнен этот фрагмент кода, используется переменная, называемая счетчиком цикла. Перед каждым выполнением блока кода производится проверка значения счетчика и, если оно достигло предельного значения, блок выполняется. Сам же этот блок называется телом цикла.

Цикл со счетчиком записывается так:

for ( <Выражение инициализации >; <Условие>; <Приращение>)

<Тело цикла>

Для задания цикла со счетчиком используется ключевое слово for. Поэтому такие циклы часто называют "циклами for".

Выражение инициализации присваивает счетчику начальное значение. Далее проверяется условие цикла, и, если его значение истинно (true), выполняется тело цикла. После этого выполняется выражение приращения, изменяющее значение счетчика, затем снова проверяется условие, и т. д., пока условие не станет ложным (false), т. е. пока счетчик не дойдет до предельного значения.

Пример цикла со счетчиком:

for (i =1; i < 11; i++) {

a += 3;

b = i * 2 + 1;

}

Этот цикл будет выполнен 10 раз. Мы присваиваем счетчику i начальное значение 1 и после каждого выполнения тела цикла увеличиваем его на единицу. Цикл перестанет выполняться, когда значение счетчика увеличится до 11, и условие цикла станет ложным.

Кроме того, допустимо использовать счетчик цикла в одном из выражений тела цикла — как это сделали мы. Счетчик i будет содержать последовательно возрастающие значения от 1 до 10, которые можно использовать в вычислениях.

Приведем еще два примера цикла со счетчиком:

for (i = 10; i > 0; i—) {

a += 3;

b = i * 2 + 1;

}

Здесь значение счетчика декрементируется. Начальное его значение равно 10. Цикл выполнится 10 раз и завершится, когда счетчик i будет содержать 0; при этом значения последнего будут последовательно уменьшаться от 10 до 1.

for (i = 2; i < 21; i += 2) b = i * 2 + 1;

А в этом примере начальное значение счетчика равно 2, а конечное — 21, но цикл выполнится опять же 10 раз. А все потому, что значение счетчика увеличивается на 2 и последовательно принимает значения 2, 4, 6… 20.

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

Цикл с постусловием

Цикл с постусловием во многом похож на цикл со счетчиком, а именно, в том, что он выполняется до тех пор, пока остается истинным условие цикла.

Причем условие проверяется не до, а после выполнения тела цикла, отчего цикл с постусловием и получил свое название. Такой цикл выполнится хотя бы один раз, даже если его условие с самого начала ложно.

Формат цикла с постусловием:

do

<Тело цикла>

while ( <Условиe >);

Для задания цикла с постусловием используются ключевые слова do и while. Поэтому такие циклы часто называют "циклами do-while".

Цикл с постусловием можно использовать различными способами. Например, так:

do {

а = а * i + 2; i = ++i;

} while (a < 100);

В рассмотренном выше примере проверяется наступление некого отвлеченного условия.

А можно записать такой цикл так:

var а = 0, i = 1; do {

а = а * i + 2;

i = ++i;

} while (i < 20);

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

Цикл с предусловием

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

while ( <Условиe>)

<Тело цикла>

Для создания цикла с постусловием используется ключевое слово while. Поэтому такие циклы называют еще "циклами while" (не путать с "циклами do-while"!).

Пример цикла с предусловием:

while (а < 100) {

а = а * i + 2;

i = ++i;

}

Прерывание и перезапуск цикла

Иногда бывает нужно прервать выполнение цикла. Для этого Flash предоставляет программистам действия break и continue.

Действие break позволяет прервать выполнение цикла и перейти к следующему за ним выражению.

while (а < 100) {

а = а * i + 2;

if (а > 50) break;

i = ++i;

}

В этом примере мы прерываем выполнение цикла, если значение переменной а превысит 50.

Собственно, мы уже знакомы с действием break. Оно использовалось в выражении выбора, где вело себя точно так же.

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

while (а < 100) {

i = ++i;

if (i > 9 && i < 11) continue;

a = a * i + 2;

}

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

 

Функции

 

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

Собственно код, ради которого и была создана функция, называется телом функции. Каждая функция, кроме того, должна иметь уникальное имя, по которому к ней можно будет обратиться. Функция также может принимать один или несколько параметров и возвращать результат, который можно использовать в выражениях.

 

Объявление функций

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

function.

function <Имя> ( [<Список параметров, разделенных запятыми>])

<Тело функции>

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

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

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

В пределах тела функции над принятыми ею параметрами (если они есть) и другими данными выполняются некоторые действия и, возможно, вырабатывается результат. Чтобы вернуть результат из функции в выражение, из которого она была вызвана, используется действие return:

return <Переменная или выражение>;

Здесь переменная должна содержать возвращаемое значение, а выражение должно его вычислять.

Пример объявления функции:

function divide(а, b) {

var с;

с = а / b;

return с;

}

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

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

Функции, объявленные в сценариях, привязанных к кадрам, кнопкам и вложенным клипам текущего клипа, "видимы" только в пределах этих сценариев (функции уровня клипа). Чтобы сделать функцию доступной во всех сценариях фильма (определить ее как глобальную), нужно использовать модификатор _globai:

function _global.glDivide(a, b) { return a / b; }

 

Вызов функций

После того как мы объявили функцию, мы можем вызвать ее из любого места кода в пределах области видимости. Для этого используется следующий формат:

< Имя функции> ( [<Список фактических параметров, разделенных запятыми>])

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

Внимание!

При вызове функции подставляйте именно фактические параметры, а не формальные, использованные в объявлении функции.

Вот пример вызова объявленной нами выше функции divide:

d = divide(3, 2);

Здесь мы подставили в выражение вызова функции фактические параметры — константы 3 и 2.

s = 4* divide (х, r) + у;

А здесь мы выполняем вызов функции с переменными в качестве фактических параметров.

Если функция не возвращает результата, то она вызывается вот так:

initVars (1, 2, 3, 6);

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

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

someClip.initVars(1, 2, 3, 6);

 

Рекурсия

И еще один важный вопрос, связанный с вызовом функций.

Мы уже узнали, что функции могут вызывать другие функции, конечно, если те уже определены. Но функции могут также вызывать и сами себя. Такой прием программирования называется рекурсией и иногда бывает очень полезен.

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

Приведем пример функции, написанной специально для применения ее в рекурсии:

function factorial (а) {

if (а == 0) {

return 1;

else

return (a * factorial(a — 1));

}

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

 

Массивы

 

Мы уже довольно много знаем о переменных и работе с ними. Но наши знания все еще неполны. Так, мы ничего пока не знаем о массивах — особом способе хранения данных, доступном в ActionScript. Давайте же выясним, что это такое.

 

Создание массивов и работа с ними

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

Внимание!

Нумерация элементов массива начинается с нуля.

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

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

var someArray;

someArray = [1, 2, 3, 4];

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

а = massive [2];

В данном примере мы получили доступ к третьему элементу массива. (Нумерация элементов массива начинается с нуля — помните об этом!)

Определять сразу все элементы массива необязательно:

someArray2 = [1, 2, 4];

Здесь мы пропустили третий элемент массива, и он остался неопределенным (т. е. будет содержать значение undefined).

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

someArray[4] = 9;

При этом будет создан новый, пятый по счету, элемент массива с индексом 4 и значением 9.

Можно даже сделать так:

someArray[7] = 9;

В этом случае будут созданы четыре новых элемента, и восьмой элемент получит значение 9. Пятый, шестой и седьмой останутся неопределенными (undefined).

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

someArray[2] = ["nl", "n2", "n3"];

После этого можно получить доступ к любому элементу вложенного массива, указав последовательно оба индекса:

stг = someArray[2][1];

Переменная str получит в качестве значения строку, содержащуюся во втором элементе вложенного массива, — "n2".

Оператор typeof возвращает для массива строку "object". Это значит, что массив имеет объектный тип (об объектах см. далее в этой главе).

 

Ссылки

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

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

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

Рассмотрим такой пример:

var myArray = ["Flash", "MX 2004"];

var newArray = myArray;

Здесь создается массив myArray с двумя элементами и далее он присваивается переменной newArray (при этом данная переменная получает ссылку на массив). Если потом мы присвоим новое значение второму элементу массива myArray:

myArray[1] = "8";

и обратимся к нему через переменную newArray:

s = newArray[1];

то переменная s получит строку "8" — новое значение второго элемента этого массива. Т. е. фактически переменные myArray и newArray указывают на один и тот же массив.

 

Объекты

 

Итак, мы познакомились с типами данных, переменными, константами, операторами, действиями, простыми и сложными выражениями, функциями и массивами. Теперь настала пора узнать о самых сложных структурах данных ActionScript — объектах.

 

Понятия объекта и экземпляра

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

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

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

Теперь давайте вернемся к нашему любимому Flash. Любой клип на его рабочем листе фактически является экземпляром объекта movieClip (об этом объекте мы поговорим далее в этой главе). Пусть имеется клип someClip, обладающий свойством width (ширина) и методом gotoAndPlay, запускающим воспроизведение анимации этого клипа с какого-то кадра. Тогда можно написать такой сценарий:

someClip.width = 200;

someClip.gotoAndPlay(3);

Здесь мы обратились к методу и свойству объекта someClip, использовав уже знакомый нам синтаксис "с точкой". А именно, отделили точкой имя объекта от имени свойства (метода).

Итак, с теорией мы разобрались. Приступим теперь к практической работе с объектами и их экземплярами.

 

Работа с объектами и их экземплярами

Перед тем как начать работу с экземпляром какого-либо объекта, его нужно создать. Создание экземпляра объекта выполняется с помощью оператора new:

<Переменная> = new <Имя объекта>([<Список параметров, разделенных запятыми>] )

После создания экземпляра объекта оператор new возвращает ссылку на него. Эта ссылка, как правило, присваивается какой-либо переменной.

Список параметров может как присутствовать, так и отсутствовать. Обычно он содержит значения, которые присваиваются свойствам экземпляра при его создании. А то, какие значения каким свойствам присваиваются, можно узнать из описания данного объекта в интерактивной справке Flash.

Вот пример создания экземпляра obj некоего объекта someObject:

var obj;

obj = new someObject(a, b);

Теперь мы можем обращаться к свойствам и методам созданного экземпляра, используя уже знакомый синтаксис "с точкой":

obj.prop1 = 0;

а = obj.prop2 + 2;

obj.method1();

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

outerObject.innerObject.prop = 0;

где outerObject — экземпляр внешнего объекта (имеющего в своем составе внутренние объекты), a innerObject — экземпляр внутреннего объекта.

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

obj ectOuter.obj ectInner.obj ectInnerlnner.prop = 10;

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

obj 2 = obj;

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

delete <Переменная, содержащая ссылку на экземпляр объекта >;

Например,

delete obj, obj 2;

Внимание!

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

Оператор typeof возвращает для экземпляра объекта строку "object". Это значит, что экземпляр объекта имеет объектный тип данных.

На заметку

Очень часто Flash сам создает экземпляры каких-либо объектов и сам же их удаляет. В частности, именно так происходит с экземплярами объекта Movieclip, т. е. клипами.

 

Несколько новых операторов и ключевых слов

А теперь самое время рассмотреть несколько новых операторов и действий, применяемых при работе с объектами и их экземплярами.

Оператор instanceof проверяет, является ли экземпляр экземпляром заданного объекта, и возвращает соответственно значение true или false. Формат его записи такой:

<Переменная> = <Экземпляр объекта> instanceof <Объект>;

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

if (obj instanceof someObject).

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

for ( <Переменная-ссылка на свойство> in < Экземпляр объекта>)

<Тело цикла>

Переменная-ссылка на свойство каждый раз получает значение очередного свойства экземпляра. Эту переменную можно использовать для получения доступа к найденному свойству.

for (k in obj) {

k = ' ' + k + ' ';

}

Приведенный фрагмент сценария просматривает все свойства экземпляра obj и добавляет к значению каждого из них пробелы слева и справа. (Предполагается, что значения всех свойств этого экземпляра имеют строковый тип.)

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

Напишем несколько выражений, обращающихся к свойствам и методам экземпляра какого-либо объекта:

someObject.propl = 1;

someObject.prop2 = 2;

someObj ect.prop3 = 3;

someObj ect.method1;

Какие длинные строки у этих выражений! А теперь перепишем их, использовав ключевое слово with:

with (someObject){

propl = 1;

prop2 = 2;

prop3 = 3;

methodl;

}

Сценарий сразу стал компактнее. И быстрее, кстати говоря.

 

Встроенные объекты ActionScript

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

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

Объект String

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

Создать экземпляр объекта String можно одним из двух способов, как показано в следующих примерах:

var s = new String("Flash");

var s = "Flash";

Как правило, чаще используется второй способ — он и компактнее в записи, и привычнее.

Свойство length объекта String позволяет получить (или, как говорят программисты, "возвращает") длину строки в символах. Например:

1 = s.length;

Метод сharAt объекта String возвращает символ строки, номер позиции которого в строке был передан в качестве единственного параметра метода:

ch = s.charAt(s.length — 1);

Внимание!

Нумерация символов строки начинается с нуля.

После выполнения выражения из приведенного примера в переменной ch окажется предпоследний символ строки s.

Метод indexof возвращает номер вхождения подстроки в строку. Если подстрока не найдена, возвращается — 1. При этом можно вторым параметром передать в метод номер вхождения, с которого начнется поиск:

<Строка>. indexOf (<Подстрока>, [<Номер вхождения >])

Например:

s = "Macromedia Flash 8";

n = s.indexOf("a", 2);

После выполнения этого сценария в переменной п окажется число 13 — именно под таким номером стоит символ "а" в слове "Flash".

Метод last indexOf схож с методом indexOf, только ищет подстроку не слева направо, а справа налево, т. е. с конца строки.

Методы toLowerCase и toUpperCase преобразуют все символы строки соответственно к нижнему и верхнему регистру.

Объект Number

Объект Number представляет собой обычное число. Пользуясь его свойствами и методами, мы можем выполнять различные манипуляции над числовыми данными.

Создается экземпляр объекта Number одним из двух способов:

var n = new Number(232);

var n = 232;

Второй способ нам уже знаком, поэтому будем пользоваться им и впредь. Метод toString объекта Number возвращает строковое представление числа:

s = n.toString ();

Помимо данного метода, объект Number имеет ряд свойств, возвращающих различные "специальные" значения. Так, свойства MIN_VALUE и MAX_VALUE позволяют узнать соответственно минимальное (примерно 5×10-324) и максимальное (примерно 1,79×10308) значения, которые могут быть присвоены числовой переменной ActionScript. А свойства NEGATIVE_INFINITY и POSITIVE_INFINITY возвращают соответственно значения — ∞ и ∞.

Объект Boolean

Объект Boolean представляет собой обычную логическую величину. С его помощью можно выполнять различные манипуляции над логическими данными.

Создается экземпляр объекта Boolean одним из двух приведенных ниже способов:

var b = new Boolean(true);

var b = true;

Метод toString объекта Boolean возвращает строковое представление логической величины — "true" или "false" соответственно:

s = b.toString ();

Объект Date

Объект Date предназначен для хранения значения даты и времени, закодированных особым способом в виде числа.

Экземпляр объекта Date создается так:

var <Имя переменной> = new Date( [<Год>, <Месяц>, [<Число>

[, <Часы >[, <Минуты> [, <Секунды> [, <Миллисекунды >]]]]]])

Вот краткое описание приведенных выше параметров:

□ Год может быть задан двумя или четырьмя цифрами. С четырьмя цифрами все просто; если же год задан двумя цифрами, то значение 0 соответствует 1900 году, а 99 — 1999 году;

□ Месяц задается значением от 0 (январь) до 11 (декабрь);

□ Дата задается значением от 1 до 31;

□ Минуты и Секунды задаются значениями от 0 до 59;

□ Миллисекунды задаются значением от 0 до 999.

Если же ни один из параметров не указан, в экземпляр объекта Date заносится текущая дата.

Объект Date имеет огромное количество методов, возвращающих или задающих различные "части" значения даты. Так, метод getMonth возвращает текущее значение месяца, а метод setMonth позволяет задать месяц, не меняя других "частей" даты. А уже знакомый нам метод toString возвращает строковое представление даты, используя региональные установки операционной системы.

Объект Array

Объект Array представляет собой массив. С его помощью можно выполнять над массивами различные манипуляции.

Создать массив можно одним из четырех приведенных ниже способов:

var arr = new Array();

var arr = new Array (<Размер>) ;

var arr = new Array(< Список элементов, разделенных запятыми>) ;

var arr = [<Список элементов, разделенных запятыми>] ;

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

Свойство length объекта Array позволяет нам узнать размер массива.

1 = arr.length;

Метод reverse объекта Array изменяет порядок следования элементов массива на противоположный. А метод toString возвращает строку, содержащую значения всех элементов массива, разделенные запятыми.

Объект Math

Объект Math предоставляет доступ к встроенным константам и математическим и тригонометрическим функциям языка ActionScript. Единственный экземпляр этого объекта создается самим Flash.

Методы sin, cos и tan объекта Math позволяют вычислить соответственно синус, косинус и тангенс угла, заданного в радианах. Метод sqrt вычисляет квадратный корень. Метод pow (х, у) возводит х в степень у.

Кроме того, объект Math имеет несколько свойств, возвращающих значение различных математических констант. Так, свойство PI возвращает значение числа π. А свойство Е возвращает значение основания натурального логарифма.

Объект Object

Объект object — простейший из объектов, предоставляемых языком ActionScript. Он обладает минимальным набором свойств и методов и служит для создания на его основе других объектов и различных вспомогательных целей.

 

Работа с клипами

 

Продолжаем изучение языка ActionScript. Поговорим о клипах (в смысле, экземплярах образцов-клипов) и выясним, какие инструменты для работы с ними предоставляет ActionScript. А таких инструментов немало…

Все находящиеся на рабочем листе клипы, для которых было задано имя, равно как и сам фильм, представляют собой экземпляры объекта MovieClip. Их создает сам Flash; нам же остается только использовать их свойства и методы.

Все клипы имеют тип данных "клип". Оператор typeof при передаче ему в качестве параметра клипа вернет строку "movieclip".

 

Доступ к нужному клипу

Прежде чем приступить к изучению объекта movieClip, нам следует выяснить, как же получить доступ к его экземплярам, т. е. клипам и самому фильму.

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

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

car.stop();

Здесь мы указываем имя соответствующего экземпляра объекта movieClip и, через точку, — метод stop, останавливающий воспроизведение анимации.

Если же мы хотим остановить вложенную анимацию клипа car из самого этого клипа, то нам нужно слегка изменить написанный нами сценарий:

this.stop();

и поместить его в этот клип. Модификатор this указывает на текущий экземпляр объекта, т. е. на клип car.

Мы можем вообще опустить модификатор this и записать наш сценарий коротко:

stop();

Но так делать не рекомендуется.

Если же нам нужно остановить воспроизведение вложенной анимации клипа wheel, являющегося составной частью клипа car, нам следует написать такой сценарий:

car.wheel.stop();

Здесь мы написали последовательно имена клипов car и wheel, разделив их точкой. Фактически мы осуществили доступ к внутреннему объекту.

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

Если нам нужно обратиться к методу или свойству анимации основного фильма из вложенного в нее клипа, мы воспользуемся модификатором _root. Так, мы можем поместить в клип wheel сценарий

_root.stop();

который остановит воспроизведение внешней анимации.

Чтобы получить доступ к внешнему объекту из внутреннего, используется модификатор _parent. Так, сценарий, помещенный в клип wheel:

_parent.stop();

остановит воспроизведение анимации клипа саг, в который вложен клип wheel.

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

Во-первых, доступ к клипу можно получить по его абсолютному пути. Абсолютный путь всегда записывается, начиная от внешней анимации, для доступа к которой используется модификатор _root. Вот пример абсолютного пути (выделен полужирным шрифтом):

_root.car.wheel .gotoAndPiay(1);

Этот сценарий будет работать в любом вложенном клипе и в самой внешней анимации, поскольку путь доступа к нужному клипу всегда один и тот же.

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

Во-вторых, мы можем задать относительный путь. Относительный путь записывается относительно текущего клипа, в котором находится сценарий. Так, если нам нужно запустить воспроизведение анимации клипа car из сценария, находящегося в клипе wheel, мы напишем такой сценарий (относительный путь выделен полужирным шрифтом):

_parent .gotoAndPiay ( 1 );

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

Для примера напишем два выражения с разными видами путей и сравним их:

_parent.gotoAndPiay(1);

_root.car.gotoAndPiay (1);

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

_parent._parent.stop();

_root.stop();

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

_root.car.engine.electricPart.ignitor.spark();

Чтобы сократить их, можно использовать уже знакомое нам выражение с ключевым словом with:

with (_root.car.engine.electricPart) {

headlightLeft.on();

headlightRight.on();

ignitor.spark();

}

Для вставки в код сценария путей доступа к клипам панель Actions предоставляет специальные средства, а именно, кнопку, расположенную над областью редактирования кода:

При нажатии этой кнопки на экране появится диалоговое окно Insert Target Path (рис. 19.1).

Большую часть этого окна занимает иерархический список клипов, вложенных в основной фильм. (Сам основной фильм там также присутствует.) Переключатели Absolute и Relative, расположенные под списком, позволяют выбрать способ записи пути, соответствующий их названиям. А в поле ввода, расположенном над списком, мы можем ввести путь доступа к клипу вручную. И, разумеется, после задания нужного пути следует нажать кнопку ОК.

 

Управление воспроизведением анимации

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

Мы уже знакомы с методом stop объекта movieClip — он останавливает воспроизведение клипа. А чтобы запустить воспроизведение клипа с того места, где он был остановлен, нужно воспользоваться методом play:

car.play();

Для осуществления перехода на какой-либо кадр клипа служат методы gotoAndPlay и gotoAndstop. Первый выполняет переход на заданный кадр и начинает воспроизведение клипа с него. Второй же метод выполняет переход на заданный кадр, но воспроизведение не инициирует. В качестве единственного параметра оба этих метода принимают номер или имя кадра; причем если значение этого параметра имеет числовой тип, то оно трактуется как номер кадра, если строковый — то как его имя. Пример с использованием числового параметра:

car.gotoAndPlay(10);

Для управления текущим клипом можно пользоваться также действиями gotoAndPlay и gotoAndstop объекта movieClip.

Формат записи их вызова таков:

gotoAndPiay|gotoAndStop ([<Имя сцены>,]<Номер или имя кадра >);

Здесь второй параметр задает, опять же, номер или имя кадра, на который будет выполнен переход. Первый же, необязательный, параметр задает имя сцены, содержащей этот кадр; если же параметр пропущен, то выполняется переход на кадр текущей сцены. Например:

gotoAndPiay(10);

gotoAndStop("Эпизод 1", х + 1);

Осталось упомянуть еще о двух методах объекта movieClip. Метод prevFrame перемещает бегунок на предыдущий кадр клипа, а метод next Frame — на следующий. Ни один из этих методов не принимает параметров.

Методы prevFrame и next Frame можно использовать, например, для создания средствами Flash презентации или слайд-шоу. Делается это так. Все изображения (слайды), которые должны войти в презентацию, помещают в отдельных кадрах фильма. К первому кадру фильма привязывается сценарий, содержащий одно-единственное выражение — stop (), которое остановит фильм на первом же кадре. После этого остается создать кнопки и привязать к ним сценарии, содержащие выражения this.prevFrame () и this.nextFrame (), которые будут выполнять переход соответственно на предыдущий и последующий кадр фильма, — и простейшее слайд-шоу готово!

 

Обработка событий, возникающих в клипах

Обработчики событий клипов имеют такой формат:

onClipEvent( <Событие>) {

<Тело обработчика>

}

Собственно, нам он уже знаком из главы 18. Вот пример такого обработчика:

onClipEvent(mouseDown) {

this.stop();

}

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

Внимание!

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

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

onClipEvent(mouseDown, mouseMove) {

stop();

}

Этот обработчик выполнится либо после щелчка мышью на клипе (событие mouseDown), либо после перемещения над клипом курсора мыши (событие mouseMove).

Теперь самое время выяснить, какие события поддерживаются объектом movieClip. Некоторые из них приведены в табл. 19.10; полный же список событий можно найти в интерактивной справке Flash.

Событие enter Frame возникает при воспроизведении очередного кадра анимации клипа. Это значит, что обработчик данного события будет выполняться постоянно с частотой, равной частоте кадров фильма, до тех пор, пока фильм не закончится. Это можно использовать для выполнения различных задач, например, для отслеживания курсора мыши.

События load и unload можно использовать для запуска или останова воспроизведения других клипов. Например, при загрузке какого-либо клипа воспроизведение другого клипа может приостанавливаться, а после выгрузки — продолжаться. Также можно написать сценарий, загружающий после выгрузки одного клипа другой и запускающий его на воспроизведение.

События mouseDown и mouseUp можно, по идее, использовать для создания на рабочем листе подобия кнопок. Но для таких целей лучше использовать полноценные кнопки Flash, создание которых было описано в главе 18.

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

on (press) {

stop();

}

И клип будет вести себя как кнопка.

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

 

Управление клипами

А теперь рассмотрим средства, предоставляемые Flash для управления клипами, находящимися на рабочем листе.

Создание новых клипов

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

Дублирование существующего клипа

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

duplicateMovieClip (<Дублируемый клип>, "<Имя создаваемого клипа>", <Порядок перекрытия нового клипа >);

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

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

Приведем пример сценария, использующего действие duplicateMovieClip и находящегося в клипе car:

duplicateMovieClip(wheel2, "wheels", 3);

(Мы только что приделали к нашему автомобилю пятое, запасное, колесо!)

Вместо действия duplicateMovieClip можно использовать одноименный метод объекта MovieClip. Вот формат его вызова:

<Дублируемый клип>. duplicateMovieClip ( "<Имя создаваемого клипа>", <Порядок перекрытия нового клипа >);

Создание нового клипа на основе образца.

Сценарные образцы

Чтобы создать совершенно новый клип, основанный на библиотечном образце-клипе, используется метод attachMovie объекта movieClip. Формат его вызова следующий:

<Клип>.attachMovie( "<Имя сценарного образца >",

"<Имя создаваемого клипа >", <Порядок перекрытия нового клипа >);

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

Дело в том, что для успешного использования в методе attachMovie образец-клип нужно превратить в так называемый сценарный — доступный для вызова из сценария. Сейчас мы выясним, как это делается.

Первым делом нужно вывести на экран панель Library. Далее найдем в списке этой панели нужный образец и выберем в контекстном или дополнительном меню пункт Linkage, после чего на экране появится давно знакомое нам диалоговое окно Linkage Properties (см. рис. 8.21).

Чтобы превратить образец в сценарный, нужно включить флажок Export for ActionScript и ввести идентификатор создаваемого образца в поле ввода Identifier. Все почти так же, как и в случае разделяемых образцов.

Далее нам нужно решить, куда будут помещены массивы данных этого сценарного образца. По умолчанию все они помещаются в первый кадр фильма и, соответственно, загружаются перед тем, как фильм начнет воспроизводиться. Если таких образцов слишком много или если они очень велики, пауза перед выводом первого кадра фильма может затянуться. Но мы можем заставить Flash поместить массив данных образца в тот кадр фильма, в котором они впервые встречаются. Для этого достаточно отключить флажок Export in first frame.

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

Вот, собственно, и все. Осталось нажать кнопку ОК окна Linkage Properties. И можно использовать готовый сценарный образец.

Приведенный ниже сценарий добавит в наш автомобиль лишнюю фару, создав ее на основе сценарного образца headlight:

_root.car.attachMovie("headlight", "headlight3", 0);

Создание "пустого" клипа

Flash также позволяет поместить на рабочий лист "пустой" клип. Это выполняется с помощью метода createEmptyMovieClip объекта movieClip. Формат вызова метода такой:

<Клип>. createEmptyMovieClip( "<Имя создаваемого клипа>",

<Порядок перекрытия создаваемого клипа >);

Метод createEmptyMovieClip вызывается для того клипа, в который нужно вложить создаваемый "пустой" клип. Оба его параметра нам уже знакомы.

Запишем сценарий с использованием этого метода:

_root.createEmptyMovieClip("tractor", 0);

Этот сценарий поместит на рабочий лист новый "пустой" клип tractor — в компанию к нашему многострадальному автомобилю. Конечно, никакого трактора там пока что нет, но — лиха беда начало…

Удаление клипа

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

removeMovieClip (<Удаляемый клип >);

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

removeMovieClip(_root.car.wheels);

Обойдемся без запаски — авось гаишник не остановит.

Для удаления клипа можно также воспользоваться методом removeMovieClip объекта movieClip. Формат его вызова очень прост:

<Удаляемый клип>. removeMovieClip();

Внимание!

С помощью действия или метода removeMovieClip можно удалить только те клипы, которые созданы из сценариев. Клипы, созданные в среде Flash, не могут быть удалены таким образом.

Изменение параметров встроенных клипов

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

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

Вот пример сценария, изменяющего координаты "фар" в нашем клипе car:

_root.car._x = 200;

_root.car.headlightl._y = _root.car.headlight2._y + 20;

Свойства _width и _height содержат соответственно ширину и высоту клипа.

Свойства _xscale и _yscale задают процент изменения размеров клипа соответственно по горизонтали и вертикали. Значения, большие 100, заставляют клип увеличить соответствующий размер, а меньшие 100 — уменьшить. Так, если задать для свойства _xscale значение 50, то клип сожмется по горизонтали вдвое.

Свойство _aipha позволяет получить или задать степень прозрачности клипа. Доступны любые целые значения от 0 (полная прозрачность) до 100 (полная непрозрачность).

Свойство _rotation задает угол поворота клипа в градусах. Например:

onClipEvent(enterFrame) {

++this._rotation;

— this._alpha;

}

Этот сценарий заставляет вложенный клип в процессе воспроизведения фильма плавно поворачиваться и одновременно плавно исчезать. Фактически мы можем создавать настоящую анимацию только средствами ActionScript.

Свойство _visible позволяет сделать клип невидимым. Оно имеет логический тип: значение true делает клип видимым, а значение false — невидимым.

onClipEvent(mouseDown) {

this._visible = ~this._visible;

}

Этот сценарий при каждом щелчке по клипу делает его то видимым, то невидимым.

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

Метод getDepth возвращает порядок перекрытия текущего клипа. Этот метод не принимает параметров.

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

var clip2 = clipl.duplicateMovieClip("clip2",

_root.getNextHighestDepth());

Это выражение создаст новый клип clip2, продублировав уже имеющийся на рабочем листе клип clip1, и поместит его "над" всеми клипами.

Метод getinstanceAtDepth возвращает ссылку на клип, имеющий заданный порядок перекрытия. Значение порядка перекрытия передается в качестве единственного параметра.

Метод swapDepths меняет значения порядка перекрытия двух клипов местами. Формат его вызова таков:

<Клип 1>. swapDepths ("<Клип 2>"|<Порядок перекрытия >);

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

Вот три примера использования этого метода:

_root.car.swapDepths("_root.tractor");

_root.car.swapDepths (10);

_root.car.swapDepths(_root.tractor.getDepth());

Получение служебной информации о клипе

Объект MovieClip поддерживает набор особых свойств, доступных только для чтения. Эти свойства возвращают различную служебную информацию, зачастую не относящуюся к самому клипу. Ниже перечислены некоторые из них.

Свойство _name возвращает имя клипа, заданное с помощью панели Properties, в строковом виде.

Свойство _target возвращает полный путь клипа в строковом виде.

Свойства _xmouse и _ymouse возвращают соответственно горизонтальную и вертикальную координаты курсора мыши относительно точки отсчета клипа. Пользуясь этими свойствами, можно контролировать перемещения мыши. Например:

onClipEvent(enterFrame) {

myCursor._x = _root._xmouse;

myCursor._y = _root._ymouse;

}

Этот сценарий заставляет вложенный клип myCursor перемещаться вслед за курсором мыши. Фактически сам клип будет вести себя как курсор мыши.

Свойство _current frame возвращает номер кадра клипа, на котором в данный момент стоит бегунок (фактически номер воспроизводимого в данный момент кадра).

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

Свойство _url возвращает интернет-адрес, с которого был загружен клип или фильм. Иногда это тоже может пригодиться.

Свойство _framesloaded возвращает количество кадров клипа, данные которых проигрыватель Flash уже загрузил. А методы getBytesLoaded и getBytesTotal помогут узнать соответственно количество загруженных байтов клипа и полный размер клипа в байтах. Используя их, мы можем создавать индикаторы загрузки клипа или фильма.

Реализация drag'n'drop

Термином "drag'n'drop" ("тащи и бросай") обозначают целый набор операций, связанных с перетаскиванием каких-либо объектов операционной системы (файлов, папок, ярлыков), системных или прикладных программ. Так, во Flash с помощью перетаскивания изменяется местоположение фрагментов изображения и бегунка панели Timeline.

Мы также можем реализовать операции "drag'n'drop" в своих фильмах Flash. Сейчас мы выясним, как это сделать.

Первое, что нам понадобится, — это действие startDrag. Оно делает клип доступным для буксировки с помощью мыши. Формат вызова действия такой:

startDrag (<Клип>, [< За центр>, <Х1>, <Y1>, <Х2>, <Y2 >]);

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

Второй параметр (за центр) имеет логический тип. Он позволяет указать точку, к которой будет автоматически "приклеиваться" курсор мыши при перетаскивании. Это может быть точка, в которой пользователь щелкнул мышью (значение false), или центр клипа (значение true).

Остальные четыре параметра позволяют описать прямоугольную область, внутри которой можно будет перетаскивать клип и за пределы которой он не сможет выйти. Через параметры X1 и Y1 задаются горизонтальная и вертикальная координаты левого верхнего угла этой области, а за координаты правого нижнего угла "отвечают" параметры Х2 и Y2. Все координаты задаются относительно внешнего клипа.

Вот два примера применения действия startDrag:

startDrag(_root.car);

startDrag(_root.car, true, 100, 100, 500, 500);

Первое выражение просто делает клип перетаскиваемым. При этом пользователь сможет "ухватить" его мышью и перетащить на новое место. Второе же выражение, кроме этого, задает дополнительные параметры перетаскиваемого клипа.

Вместо действия startDrag можно использовать одноименный метод объекта movieClip:

<Kлип>.startDrag([<За центр>, [<Х1>, <Y1>, <Х2>, <Y2 >]]);

После вызова действия или метода startDrag клип останется перетаскиваемым на сколь угодно долгое время. Чтобы завершить операцию "drag'n'drop", например, если пользователь отпустит кнопку мыши, нужно вызвать действие или метод stopDrag. Вот так (действие):

stopDrag();

или так (метод):

_root.car.stopDrag();

На заметку

Для завершения операции "drag'n'drop" также можно вызвать еще раз действие или метод startDrag , но уже для другого клипа. Только один клип в данный момент времени может быть перетаскиваемым.

Теперь давайте подумаем, как применить только что полученные сведения в деле написания реальных сценариев-обработчиков событий.

Для запуска и завершения операции "drag'n'drop" можно использовать обработчики событий mouseDown и mouseUp клипа — это очевидно. Давайте напишем эти обработчики и привяжем их к клипу, который нужно сделать перетаскиваемым.

onClipEvent(mouseDown) {

this.startDrag(false);

}

onClipEvent(mouseUp) {

this._x = _root._xmouse;

this._y = _root._ymouse;

this.stopDrag();

}

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

Объект MovieClip предоставляет доступное только для чтения свойство _droptarget, возвращающее ссылку на так называемую "цель" операции "drag'n'drop" — на клип, в который был "брошен" перетаскиваемый клип. Можно проверить результат, возвращаемый этим свойством, и, в зависимости от него, завершить или не завершить операцию перетаскивания.

Здесь имеет место небольшое затруднение. Дело в том, что свойство _droptarget возвращает результат в особом формате, применяемом в старых версиях Flash (это версии 1–4). Это так называемая "запись со слэшем", когда в качестве разделителя между именем экземпляра объекта и названием его свойства или метода используется косая черта (/), а не точка. Для того чтобы преобразовать "запись со слэшем" в знакомую нам "запись с точкой", нужно воспользоваться встроенной во Flash функцией evai.

Давайте перепишем сценарии-обработчики событий mouseDown и mouseUp так, чтобы они не позволяли пользователю "бросить" перетаскиваемый клип в клип по имени forbiddenArea. Сценарии будут выглядеть так:

onClipEvent(mouseDown) {

this.startDrag(false);

oldX = this._x;

oldY = this._y;

}

onClipEvent(mouseUp) {

if (eval(this._droptarget)!= _root.forbiddenArea) {

this._x = _root._xmouse;

this._y = _root._ymouse;

} else {

this._x = oldX;

this._y = oldY;

}

this.stopDrag();

}

Теперь первый обработчик, помимо запуска операции "drag'n'drop", сохраняет изначальные координаты перетаскиваемого клипа в переменных oldX и oldY. Второй же обработчик, обнаружив, что пользователь перетащил клип в "запрещенное место", восстанавливает изначальное положение перетаскиваемого клипа. В обоих случаях операция "drag'n'drop" завершается.

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

Создание фигурного курсора мыши

Очень многие приложения (не только созданные во Flash, но и обычные, работающие в системе Windows) "щеголяют" фигурными курсорами мыши. Давайте выясним, как создать такой курсор средствами Flash.

Предположим, что мы создали образец-клип и нарисовали в нем курсор желаемой формы. Далее мы поместили экземпляр созданного клипа на рабочий лист и назвали его cursor. Теперь, чтобы превратить этот клип в фигурный курсор мыши, привяжем к нему такой обработчик события по имени load:

onClipEvent(load) {

this.startDrag(true);

}

Обработчик load сразу же после загрузки клипа делает его перетаскиваемым. После этого клип cursor будет всегда перемещаться за курсором мыши и фактически сам станет курсором, чего мы и добивались.

Казалось бы, все замечательно. Одно плохо: "родной" курсор мыши, рисуемый самой системой Windows, портит всю картину. Его нужно спрятать. Для этого воспользуемся методом hide пока еще не изученного нами объекта Mouse (он будет рассмотрен далее в этой главе). Этот метод скрывает системный курсор мыши.

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

onClipEvent(load) {

Mouse.hide();

this.startDrag(true);

}

Вот теперь все работает, как надо.

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

this.startDrag(true, 200, 100, 600, 400);

После этого наш фигурный курсор будет "заперт" в указанных границах.

Выявление совпадений и касаний

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

В нашем случае, однако, все намного проще. Разработчики Flash предусмотрели в объекте movieClip особый метод hitTest. С его помощью мы можем проверить, находится ли заданная точка внутри клипа или касаются ли друг друга два отдельных клипа.

Метод hitTest имеет два формата вызова. Первый из этих форматов позволяет выяснить совпадение точки и клипа:

<Клип>. hitTest(<Х>, <Y>, <Проверять контур >);

Понятно, что первые два параметра определяют соответственно горизонтальную и вертикальную координаты нужной нам точки. Третий параметр имеет логический тип и позволяет указать, что считать границами клипа. Если этот параметр имеет значение true, Flash считает границами клипа контур содержащейся в нем графики. В случае значения false Flash "мысленно" вписывает клип в невидимый прямоугольник и считает границами клипа его контур.

Если заданная точка находится внутри клипа, метод hitTest возвращает значение true. В противном случае — значение false. Возвращаемое значение можно использовать в условном выражении или где-либо еще.

Давайте проверим, как работает этот метод. Создадим новый клип, представляющий собой сложную фигуру из множества кривых. Поместим его на рабочий лист и присвоим ему имя hit. После этого привяжем к этому клипу такой обработчик события enterFrame:

onClipEvent(enterFrame) {

if (this.hitTest(_root._xmouse, _root._ymouse, true)) {

this._alpha = 50;

} else { this._alpha = 100;

}

}

Этот сценарий-обработчик события проверяет, находится ли курсор мыши внутри контура нашего клипа. Если это так, клип делается полупрозрачным, в противном случае — полностью непрозрачным (видимым).

В нашем случае метод hitTest проверяет только "попадание" в сам клип, поскольку его третий параметр имеет значение true. Если же передать значение false, то метод станет проверять попадание в воображаемый прямоугольник, описанный вокруг нашего клипа. Это более грубая проверка совпадения точки и клипа.

Второй формат метода hitTest позволит нам проверить на совпадение два различных клипа, т. е. проверить, накладываются они друг на друга или перекрываются:

<Клип !>.hitTest (<Клип 2 >);

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

Нам осталось проверить работу метода. Создадим новый образец-клип со сложной фигурой, поместим его экземпляр на рабочий лист, сделаем его поменьше и назовем cursor. К первому (и единственному) кадру фильма привяжем вот такой небольшой сценарий:

_root.cursor.startDrag(true);

Этот сценарий заставляет клип cursor двигаться за мышью, т. е. превращает его в фигурный курсор.

Теперь напишем сценарий-обработчик события enter Frame для клипа hit, так чтобы он проверял касание клипов cursor и hit одного другим:

onClipEvent(enterFrame) {

if (this.hitTest(_root.cursor)) {

this._alpha = 50;

} else { this._alpha = 100;

}

}

 

Работа с графикой

Хоть Flash и предоставляет мощные средства рисования графики и создания анимации, иногда бывает нужно кое-что дорисовать уже во время воспроизведения фильма. Например, если мы собираемся создать фильм, который в процессе воспроизведения будет выводить на рабочий лист график какой-либо функции, нам потребуются средства для рисования этого самого графика. Что в этом случае может предложить нам Flash?

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

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

Программное рисование графики

В этом разделе мы поговорим о том, как выполняется рисование графики из сценариев и какие методы объекта movieClip для этого используются.

Но сначала нужно уяснить два момента.

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

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

Перейдем к делу.

Для рисования графики из сценариев используется так называемое программное перо (не путать с инструментом рисования "перо"!). С помощью особых методов объекта movieClip это перо можно устанавливать в определенные точки на рабочем листе и проводить им линии, прямые и кривые. Также с помощью программного пера задаются точки, где должны быть помещены заливки.

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

<Клип>. moveTo (<Х>, <Y >);

Понятно, что в качестве параметров методу передаются горизонтальная и вертикальная координаты точки, в которую нужно переместить программное перо. Эти координаты отсчитываются относительно точки отсчета клипа.

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

<Клип>.lineTo(<Х>, <Y>);

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

Вот пример сценария, рисующего в клипе paintBox треугольник:

with (_root.paintBox) {

moveTo(100, 200);

lineTo(300, 200);

lineTo(200, 100);

lineTo (100, 200);

}

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

<Клип >.curveTo (<АХ>, <AY>, <Х>, <Y >);

Параметры Х и Y определяют соответственно горизонтальную и вертикальную координаты конечной точки кривой (начальной же точкой является, опять же, точка, в которой в данный момент находится программное перо). А параметры АХ и AY указывают горизонтальную и вертикальную координаты точки искривления. Все эти координаты отсчитываются, опять же, относительно точки отсчета клипа.

Вот пример сценария, рисующего нечто похожее на окружность:

with (_root.paintBox) {

moveTo(300, 300);

curveTo(400, 300, 400, 200);

curveTo(400, 100, 300, 100);

curveTo(200, 100, 200, 200);

curveTo(200, 300, 300, 300);

}

Увы — более удобных способов программно нарисовать окружность Flash не предлагает. Приходится или создавать образец, рисовать в нем окружность и программно порождать от него экземпляры, или выходить из положения вышеописанным способом. Хотя, можно еще описать окружность в виде функции и нарисовать ее график.

Для рисования линии, неважно — прямой или кривой, будут использованы текущие параметры ее стиля: толщина, цвет и прозрачность. Задание текущего стиля выполняется с помощью метода linestyle. Он вызывается вот так:

<Клип>. lineStyle ([<Толщина линии>, [<Цвет линии>,

[ <Прозра чность линии>] ]]);

Толщина линии задается в пикселах, от 0 до 255. Если она не задана, то линия нарисована не будет. Цвет линии задается в формате 0×RRGGBB, где RR — доля красного цвета, GG — зеленого и ВВ — синего соответственно. Пример задания цвета: 0×22FF44. Прозрачность линии может принимать значения от 0 (полная прозрачность) до 100 (полная непрозрачность).

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

Поэтому сценарий, рисующий треугольник, нам придется переписать:

with (_root.paintBox) {

lineStyle(2, 0x000000);

moveTo(100, 200);

lineTo (300, 200);

lineTo(200, 100);

lineTo (100, 200);

}

Здесь мы с помощью метода linestyle задали стиль линии: толщина в 2 пиксела и черный цвет. После этого треугольник уж точно будет нарисован.

А теперь давайте посмотрим на только что нарисованный треугольник и подумаем: чего же в нем не хватает? В главе 3 мы выяснили, что, если нарисовать замкнутую фигуру, Flash автоматически создаст заливку; при этом не имеет значения, какой инструмент рисования использовался. Здесь же заливки нет. Почему?

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

Для создания заливки служат два метода. Первый из них — beginFill — указывает Flash, что с этого момента нужно отслеживать все операции программного рисования и после создания замкнутой фигуры учесть на будущее, что ей нужна заливка. Второй — endFill — прекращает отслеживание операций рисования и рисует собственно заливку (если, конечно, ее можно нарисовать, т. е. если нарисованный нами контур полностью или частично замкнут).

Формат вызова метода beginFill такой:

<Клип>. beginFill( [<Цвет заливки>, [ <Прозрачность заливки>] ]);

Цвет заливки задается в том же формате 0×RRGGBB, а прозрачность — значением от 0 до 100. Если эти параметры не заданы, будут использованы текущие значения цвета и прозрачности заливки — те, что были указаны при предыдущем вызове метода beginFill. Поэтому при самом первом вызове этого метода нужно указать оба его параметра.

Метод endFill не принимает ни одного параметра:

<Клип>. endFill();

Теперь еще раз перепишем сценарий, чтобы он рисовал треугольник с заливкой:

with (_root.paintBox) {

lineStyle(2, 0×000000);

beginFill(0×222233, 100);

moveTo(100, 200);

lineTo(300, 200);

lineTo (200, 100);

lineTo(100, 200);

endFill ();

}

С помощью метода beginFill создается обычная, сплошная заливка. Если же нужно создать градиентную заливку, то придется воспользоваться методом beginGradientFill в паре с методом endFill. Полное описание этого метода приведено в интерактивной справке Flash.

Чтобы удалить все, что было нарисовано программно, нужно вызвать метод clear:

_root.paintBox.clear();

При этом будет также сброшен заданный с помощью метода linestyie стиль линий. Графика же, нарисованная вручную, удалена не будет.

Пример сценария, рисующего график функции

А теперь давайте попрактикуемся и напишем сценарий, рисующий график функции f(x) = х 2 . Это, скорее, курьез, чем реально необходимый пример, но он поможет нам глубже изучить методы рисования объекта movieClip.

Сначала создадим новый документ Flash. И привяжем к единственному кадру анимации следующий сценарий:

var dx = 200;

// Величина отступа от левого края рабочего листа

var х = 0;

var у = 0;

// Временные переменные

// Каждая точка графика будет представлять собой небольшой квадрат с

// черной заливкой

lineStyle(1, 0×000000);

// Стиль линий контура этого квадрата

for(х = -20; х < 21; х++) {

// Используем цикл со счетчиком, чтобы вычислить значения функции

// для аргументов в пределах от -20 до 20

у = х * х;

// Вычисляем значение функции

beginFill(0×000000);

// Начинаем рисование заливки квадрата

// Рисуем квадрат

endFill ();

// Заканчиваем рисование заливки

}

Теперь запустим на воспроизведение готовый фильм в отдельном окне. Работает!

Правда, график наш рисуется вверх ногами. Чтобы исправить этот огрех, перепишем наш сценарий. Теперь он будет выглядеть вот так (добавленный и измененный код выделен полужирным шрифтом):

var dx = 200;

dy = 400;

// Величина отступа от верхнего края рабочего листа

var х = 0;

var у = 0;

lineStyle(1, 0×000000);

for(х = -20; х < 21; х++) {

у = х * х;

beginFill(0×000000);

moveTo(dx + х — 1, dy — у + 1);

lineTo(dx + x + 1, dy — у + 1);

lineTo(dx + x + 1, dy — у — 1);

lineTo(dx + х — 1, dy — у — 1);

lineTo(dx + x — 1, dy — у + 1);

endFill ();

}

После этих изменений наш график будет нарисован нормально.

Программное управление масками

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

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

<Маскируемый клип>. setMask (<Клип-маска >);

Самое интересное заключается в том, что оба клипа совсем не обязательно должны находиться в разных слоях (о слоях см. главу 5, о маскирующих слоях — главу 14). Кроме того, и маскирующий, и маскируемый клипы могут содержать сложную анимацию и даже двигаться. Ух, каких чудес можно натворить!

Давайте создадим новый документ Flash, поместим на рабочий лист клип, содержащий любое растровое изображение, а на него наложим клип с какой-либо простой геометрической фигурой. Назовем нижний клип masked, а верхний — mask. После этого привяжем к единственному кадру анимации такой вот сценарий:

masked.setMask(mask);

mask.startDrag(true);

Первое выражение этого сценария маскирует клип-растровое изображение masked клипом mask. Второе выражение заставляет клип mask (т. е. маску) перемещаться вслед за курсором мыши.

Теперь запустим на воспроизведение созданный фильм в отдельном окне и начнем перемещать курсор мыши с места на место. Забавно получилось, не правда ли?

Кстати, маски, созданные путем вызова метода setMask, имеют приоритет над масками, созданными вручную. Иными словами, если мы создадим маскирующий слой с клипом-маской mask и замаскируем им другой клип masked, то выражение:

mask.setMask(masked);

сделает клип masked маской, а клип mask — маскируемым.

Маскируемый клип в данный момент времени может иметь только одну маску. Так, если для клипа masked вызвать метод setMask еще раз, но передать ему в качестве параметра клип mask2, то он станет новой маской для masked, а предыдущая маска mask "уйдет в отставку".

Чтобы убрать маску совсем, достаточно вызвать метод setMask с параметром null:

masked.setMask(null);

 

Работа с кнопками

 

А теперь поговорим о кнопках и работе с ними с помощью сценариев. (Подробнее о кнопках см. главу 18.)

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

Оператор typeof для кнопки возвращает строку "object" — это значит, что кнопка относится к объектному типу данных.

 

Свойства и методы объекта Button

По своим свойствам и методам объект Button во многом похож на объект movieclip. Имея весьма схожие наборы свойств и методов, эти два объекта зачастую ведут себя одинаково. В частности, объект Button поддерживает свойства х, _у, _xmouse, _ymouse, _height, _width, _alpha и _rotation, уже знакомые нам по объекту movieClip. Однако объект Button не поддерживает методы play, stop, gotoAndPiay, gotoAndStop и подобные им, так как назначение его все же иное, чем у объекта movieclip. Так что кнопку можно рассматривать как очень специализированный, "урезанный" вариант клипа.

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

Свойство enabled позволяет разрешить или запретить пользователю нажимать кнопку. Оно имеет логический тип: значение true разрешает доступ к кнопке, а значение false — запрещает.

Свойство _visibie позволяет сделать кнопку видимой или невидимой. Оно имеет логический тип: значение true делает кнопку видимой, а значение false — невидимой. При этом невидимая кнопка также недоступна для нажатия.

Свойство useHandCursor задает, какую форму примет курсор мыши, если поместить его над кнопкой. Если задано значение true, то отображается курсор в виде "указующего перста" (как над гиперссылкой). Если же задано значение false, то курсор имеет вид обычной стрелки.

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

Фокус ввода можно перемещать с одной кнопки на другую, согласно особой последовательности, называемой порядком обхода. Каждая кнопка имеет свой уникальный номер в этом порядке. Для перехода на элемент управления с большим номером в порядке обхода нужно нажать клавишу <Таb>, для перехода на элемент управления с меньшим номером — комбинацию клавиш +.

Для задания порядка обхода кнопок Flash служат два свойства объекта Button. Рассмотрим их.

Свойство tabindex задает номер в порядке обхода для данной кнопки. Значением этого свойства может быть любое целое неотрицательное число.

Задать порядок обхода можно с помощью приведенного ниже сценария, привязанного к первому кадру анимации фильма:

btnForward.tabindex = 0;

btnBackard.tabindex = 1;

btnStop.tabindex = 2;

Также для этого можно воспользоваться панелью Accessibility, подробно описанной в главе 20.

Если ни для одной кнопки в фильме Flash не задан номер в порядке обхода (т. е. значение свойства tabindex равно undefined), Flash будет применять порядок обхода по умолчанию, и кнопки будут "обходиться" по нажатию клавиши <Таb> в том порядке, в котором они были созданы на рабочем листе. Также нужно иметь в виду, что значение undefined меньше любого числового, поэтому кнопки, для которых свойство tabindex не было задано, будут в порядке обхода первыми.

Свойство tabEnabied позволяет вообще убрать кнопку из порядка обхода, после чего ей нельзя будет дать фокус ввода с помощью клавиатуры (хотя нажимать ее щелчком мыши будет можно). Это свойство имеет логический тип: значение true или undefined предоставляет возможность дать кнопке фокус ввода с помощью клавиатуры, а значение false такую возможность отменяет.

 

Обработка событий, возникающих в кнопках

Сценарий-обработчик события, возникающего в кнопке, как мы помним из главы 18, имеет такой формат записи:

on (<Событие>) {

<Тело обработчика>

}

Например:

on (press) {

_root.stop();

}

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

Все события, поддерживаемые объектом Button, перечислены в табл. 19.11.

 

Создание и удаление кнопок из сценариев

Ранее в этой главе мы говорили, что имеется возможность создавать и удалять клипы из сценариев, пользуясь соответственно методами attachMovie и removeMovieClip объекта movieclip и аналогичными действиями. Такая возможность реализована и для кнопок. Так, мы можем создать на рабочем листе новую кнопку в процессе воспроизведения фильма, привязав к кадру анимации такой сценарий:

_root.attachMovie("button", "button2", 1);

А затем мы можем удалить эту кнопку:

_root.button2.removeMovieClip();

 

Работа с текстовыми блоками

 

Текстовые блоки, описанные в главе 7, служат для отображения текста. Они бывают трех видов:

□ статические текстовые блоки, служащие для отображения текста, который не изменяется в процессе воспроизведения фильма или работы Flash-приложения. Это могут быть надписи, заголовки, инструкции и пр.;

□ поля ввода, служащие для ввода текста пользователем;

□ динамические текстовые блоки, служащие для вывода текста, который изменяется в процессе воспроизведения фильма или работы Flash-приложения. Это может быть, например, текст, содержащий результаты работы приложения.

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

 

Объект TextField и его свойства и методы

И поля ввода, и динамические текстовые блоки представляются одинаково — как экземпляры объекта TextField. Они также создаются самим Flash для каждого поля ввода или динамического текстового блока, помещенного на рабочий лист и имеющего имя.

Оператор typeof для специального текстового блока возвращает строку "object", т. е. специальный текстовый блок имеет объектный тип данных.

Объект TextField имеет множество свойств и методов. Мы опишем только некоторые из них; полное описание этого объекта приведено в интерактивной справке Flash.

Прежде всего, объект Text Field поддерживает свойства _х, _у, _xmouse, _ymouse, _height, _width, _alpha и _rotation, знакомые нам по объекту movieclip. Кроме того, он обладает свойствами enabled, _visible, tabEnabled и tablndex, которые поддерживаются также объектом Button.

Да-да, как и в случае кнопок, мы можем назначать для полей ввода номера в порядке обхода с помощью сценария вида:

txtNamel.tablndex = 0;

txtName2.tablndex = 1;

txtEmail.tablndex = 2;

btnOK.tablndex = 3;

btnCancel.tablndex = 4;

или панели Accessibility (см. главу 20).

Свойство type объекта Text Field служит для задания вида данного экземпляра объекта Text Field, т. е. определяет, будет это поле ввода или динамический текстовый блок. Это свойство имеет строковый тип: значение "input" превращает экземпляр объекта Text Fie id в поле ввода, а значение "dynamic" — в динамический текстовый блок. Свойство доступно как для чтения, так и для записи, а это значит, что мы можем превращать поля ввода в динамические текстовые блоки и наоборот.

Свойство text позволяет получить или задать текст, находящийся в поле ввода или динамическом текстовом блоке. Оно имеет строковый тип.

Пример выражения со свойством text:

txtName.text = "Vasya Pupkin";

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

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

var name: String = "";

txtName.variable = "name";

name = "Vasya Pupkin";

Свойство html позволяет разрешить или запретить вводить в поле ввода или динамический текстовый блок текст, отформатированный с помощью тегов HTML. Оно имеет логический тип: значение true разрешает вводить HTML-текст, а значение false — запрещает.

Свойство htmlText используется для получения или задания значения поля ввода или динамического текстового блока в том случае, если ввод HTML-текста разрешен.

txtName.html = true;

txtName.htmiText = "<B>Vasya</B> <I>Pupkin</I>";

Подробнее о поддержке тегов HTML в текстовых блоках рассказано в интерактивной справке Flash.

Свойство maxChars позволяет задать максимальное количество символов, которое может быть введено в поле ввода пользователем. (Количество символов, помещаемое в это поле ввода из сценариев, в любом случае не ограничено.) Это свойство принимает неотрицательные числовые значения; значение null отменяет ограничение на количество вводимых символов.

Доступное только для чтения свойство length возвращает количество символов, введенное в поле ввода.

Свойство multiline имеет логический тип и позволяет сделать поле ввода или динамический текстовый блок многострочным. Для этого достаточно присвоить этому свойству значение true. А присвоение значения false вновь делает поле ввода или динамический текстовый блок однострочным.

Свойство password позволяет превратить обычное поле ввода в поле ввода пароля. Для этого достаточно присвоить этому свойству логическое значение true. Присвоение значения false вновь делает поле ввода обычным.

Свойство selectable позволяет сделать поле ввода или динамический текстовый блок выделяемым; при этом пользователь сможет выделять текст, находящийся в данном поле или текстовом блоке, и копировать его в буфер обмена Windows. Это свойство имеет логический тип: значение true разрешает пользователю выделять текст, а значение false — запрещает.

Свойство wordwrap используется в том случае, если необходимо, чтобы текст в поле ввода или динамическом текстовом блоке переносился по строкам. Оно имеет логический тип: значение true устанавливает автоматический перенос строк текста, значение false его отменяет.

Помимо описанных, объект Text Field поддерживает несколько свойств, задающих форматирование текста. Все эти свойства перечислены в табл. 19.12.

Обработка событий, возникающих в текстовых блоках

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

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

function txtNameChanged() {

needToSave = true;

}

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

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

Да, но как собственно привязать ее к текстовому блоку? Очень просто. Объект TextField поддерживает набор свойств, соответствующих поддерживаемым им событиям. Мы просто присвоим написанную нами функцию нужному свойству, вот так:

_root.txtName.onChanged = txtNameChanged;

Да, такие "фокусы" считаются стандартными в языке ActionScript! А свойство onChanged, соответствующее событию, происходящему при изменении содержимого поля ввода, получит тип данных "функция".

На заметку

Оператор typeof при передаче ему в качестве параметра функции или переменной, которой присвоена функция, вернет строку "function".

Всего объект TextField поддерживает четыре события. Связанные с ними свойства, которым нужно присвоить соответствующую функцию-обработчик, перечислены в табл. 19.13.

На заметку

Свойства, соответствующие событиям, поддерживают также объекты movieClip и Button . Их описание можно найти в интерактивной справке Flash.

Использование перехватчиков событий

Мы уже знаем два способа обработки событий. Первый способ — это использование для написания сценариев-обработчиков событий специальных действий (onClipEvent и on). Второй способ — это присвоение соответствующему свойству функции, которая будет вызываться в ответ на это событие и, таким образом, станет его обработчиком. Первый способ компактнее, но работает не для всех объектов, второй же не столь компактен, но зато универсален (именно с его помощью обрабатываются события в текстовых блоках).

Однако Flash предоставляет нам еще один способ обработки нужного события — с использованием так называемого перехватчика событий (в терминологии Flash — "listener", "слушатель"). Это экземпляр объекта object, содержащий особые свойства, соответствующие обрабатываемым им событиям. Этим свойствам присваиваются функции-обработчики соответствующих событий, после чего перехватчик особым образом привязывается к экземпляру объекта, события которого нужно обработать.

В случае текстового блока с помощью перехватчика могут быть обработаны события onchanged и onScroller. (Это значит, что перехватчик должен содержать свойства onchanged и onScroller.) Вот пример сценария, создающего такой перехватчик (предположим, что функции обработки нажатия клавиш fOnChanged и fOnScroller уже описаны):

myListener = new Object ();

myListener.onchanged = fOnChanged;

myListener.onScroller = fOnScroller;

Изначально объект object не содержит свойств onchanged и onScroller. Они будут созданы в экземпляре этого объекта myListener, который мы только что создали, и будут "принадлежать" только этому экземпляру.

Для привязки перехватчика к текстовому блоку используется метод addListener объекта Text Field. Этот метод принимает единственный параметр — ссылку на перехватчик.

txtName.addListener(myListener);

Это выражение привязывает созданный нами перехватчик к полю ввода txtName.

Один и тот же перехватчик можно привязать сразу к нескольким текстовым блокам:

txtName2.addListener(myListener);

txtFamily.addListener(myListener);

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

Чтобы "отвязать" от текстового блока ненужный более перехватчик, воспользуемся методом removeListener. Этот метод в качестве единственного параметра также принимает ссылку на перехватчик.

txtName.removeListener(myListener);

Теперь останется только совсем удалить ненужный перехватчик:

delete myListener;

Создание и удаление текстовых блоков из сценариев

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

Для создания поля ввода или динамического текстового блока используется метод createTextField объекта movieClip. Формат его вызова таков:

<Клип>. createTextField( <Имя >, <Порядок перекрытия>, <Х>, <Y>,

<Ширина>, <Высота>) ;

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

Нужно помнить, что с помощью этого метода создается динамический текстовый блок, т. е. свойство type соответствующего экземпляра объекта TextField сразу же получит значение "dynamic". Чтобы преобразовать этот экземпляр в поле ввода, нужно присвоить свойству type строку "input". Например:

_root.createTextField("txtName", 0, 100, 100, 200, 50);

_root.txtName.type = "input";

_root.txtName.variable = "Name";

Этот сценарий создает поле ввода txtName и привязывает его к переменной Name.

Для удаления созданного с помощью метода createTextField текстового блока используется метод removeTextField объекта TextField:

_root.txtName.removeTextField();

Внимание!

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

Использование объекта Selection

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

Метод get Focus этого объекта возвращает в строковом виде имя переменной, привязанной к текстовому блоку, имеющему в данный момент фокус ввода. Если к текстовому блоку не привязана переменная или если фокус ввода имеет кнопка или клип, то возвращается путь (также в строковом виде). Если ни один текстовый блок, ни одна кнопка и ни один клип не имеют фокуса, возвращается значение null.

Для того чтобы дать какому-либо текстовому блоку (а также кнопке или клипу) фокус ввода, нужно вызвать метод set Focus. В качестве единственного параметра этому методу передается путь в строковом виде:

Selection.setFocus("_root.txtName");

Selection.setFocus("_root.btnOK");

Чтобы снять фокус ввода со всех элементов управления, достаточно передать методу setFocus в качестве параметра значение null.

С помощью объекта selection мы можем получить позицию текстового курсора в поле ввода. Для этого достаточно вызвать не принимающий параметров метод get Caret index, который вернет нам номер символа, на котором стоит курсор. (Не стоит забывать, что нумерация символов начинается с нуля.) Если же ни одно поле ввода не имеет фокуса, возвращается значение — 1.

Методы getBeginindex и getEndindex возвращают номера соответственно начального и конечного символа выделенного в текстовом блоке фрагмента текста. Если ничего не выделено, также возвращается значение — 1.

Можно выделить нужный фрагмент текста, воспользовавшись методом setSelection. Первый параметр этого метода должен иметь значение, равное номеру первого символа выделяемого фрагмента, а второй параметр — значение, равное номеру последнего символа. Вот так:

Selection.setSelection(10, 30);

Чтобы просто поставить текстовый курсор в требуемую позицию, нужно передать методу setSelection номер нужного символа и в первом, и во втором параметре:

Selection.setSelection(10, 10);

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

myListener = new Object ();

myListener.onSetFocus = fOnSetFocus;

Selection.addListener(myListener);

Это пример создания и привязки перехватчика к объекту selection. Функция fOnsetFocus выполняет собственно обработку события onset Focus; определение этой функции было опущено.

 

Обработка нажатий клавиш клавиатуры

 

Для обработки нажатия клавиш клавиатуры служит объект Key. Его единственный экземпляр, также носящий имя Key, создается самим Flash.

 

Свойства и методы объекта Key

Два важнейших метода, которые обязательно понадобятся нам для обработки нажатий клавиш, — это методы getAscii и getcode. Первый метод возвращает код символа ASCII, который присвоен нажатой клавише. Второй метод возвращает так называемый виртуальный код нажатой клавиши — низкоуровневый код, позволяющий узнать, какая клавиша на клавиатуре была нажата. Оба эти метода не принимают параметров.

Вот пример выражений вызова этих методов:

codel = Key.getAscii(); code2 = Key.getCode();

Код символа ASCII зависит от текущей кодировки. Коды символов кодировки Windows 1251 приведены в интерактивной справке Flash; там же приведены и виртуальные коды клавиш.

Еще один полезный метод объекта Key — метод isDown. Он принимает единственный параметр — виртуальный код клавиши — и возвращает значение true, если эта клавиша нажата. Например:

if (Key.isDown(Key.ENTER)) {. }

Приведенное выше выражение проверяет, была ли нажата клавиша .

Метод isToggied возвращает значение true, если в момент его вызова была включена одна из клавиш-переключателей: или . Он принимает единственный параметр — числовое значение 20 (виртуальный код клавиши ) или 144 (виртуальный код клавиши ).

Пример вызова метода isToggied:

if (Key.isToggied(20)) { s = s.toLowerCase; }

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

 

Обработка нажатий клавиш в клипах

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

Обработка нажатий клавиш в клипах

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

Создадим новый документ Flash. В нем создадим образец-клип, содержащий простую геометрическую фигуру, например, круг. Поместим экземпляр этого образца на рабочий лист и назовем его circle. Этот экземпляр мы заставим перемещаться по листу в ответ на нажатия клавиш — стрелок.

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

onClipEvent(load) {

d = 1;

}

Обработчик события load помещает значение в переменную d сразу после загрузки клипа. Эта переменная задает величину перемещения нашего экземпляра при нажатии любой клавиши-стрелки. Можно задать и большее число, чтобы заставить клип двигаться быстрее.

Второй фрагмент сценария выглядит более сложным:

onClipEvent(keyDown) {

switch (Key.getCode()) {

case Key.UP:

_root.circle._y — = d;

break;

case Key.DOWN:

_root.circle._y += d;

break;

case Key.LEFT:

_root.circle._x — = d;

break;

case Key.RIGHT:

_root.circle._x += d;

break;

}

}

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

Теперь запустим созданный фильм на воспроизведение в отдельном окне. Он работает!

Конечно, наш пример очень прост. Тем не менее, руководствуясь им, можно создавать и несравнимо более сложные вещи. Например — как насчет игры "15", реализованной на Flash? Или всем известного "Сапера"?

Обработка нажатий клавиш с помощью перехватчика

Второй способ обработать нажатия клавиш — использовать перехватчик. Этот перехватчик должен иметь свойства onKeyUp и onKeyDown, которым должны быть присвоены функции, обрабатывающие соответствующие события. Событие onKeyDown возникает при нажатии клавиши, а событие onKeyUp — при ее отпускании.

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

Рассмотрим этот сценарий по частям.

Сначала:

var d = 1;

Это уже знакомая нам переменная, задающая величину смещения клипа за один шаг.

А дальше:

function fOnKeyDown() {

switch (Key.getCode()) {

case Key.UP:

_root.circle._y — = d;

break;

case Key.DOWN:

_root.circle._y += d;

break;

case Key.LEFT:

_root.circle._x — = d;

break;

case Key.RIGHT:

_root.circle._x += d;

break;

}

}

А это объявление функции, обрабатывающей событие onKeyDown. Ее код практически совпадает с кодом обработчика события keyDown для клипа, написанного нами ранее.

И, наконец:

var myListener = new Object ();

myListener.onKeyDown = fOnKeyDown;

Key.addListener(myListener);

Этот фрагмент кода создает и привязывает к объекту Key перехватчик. Собственно, это тоже нам знакомо.

 

Взаимодействие с мышью

Для взаимодействия с мышью служит объект Mouse. Единственный экземпляр этого объекта под именем Mouse создается самим Flash.

Прежде всего, этот объект предоставляет методы hide и show. Первый метод скрывает курсор мыши, а второй — вновь выводит его на экран. Ни один из них не принимает параметров. Эти методы используются, как правило, при создании фигурных курсоров мыши.

Объект Mouse поддерживает также три события:

□ событие onMouseDown возникает при нажатии левой кнопки мыши;

□ событие onMouseUp возникает при отпускании левой кнопки мыши;

□ событие onMouseMove возникает при любом перемещении мыши;

□ событие onMouseWheel возникает при прокрутке колесика мыши, если такое имеется.

Для обработки этих событий используются перехватчики. Все функции, обрабатывающие их, не принимают параметров, за исключением функции-обработчика события onMouseWheel. Она имеет такой формат:

function <Имя> ( [<Смещение>, <Клип, над которым находится курсор мыши>])

Первый из необязательных параметров этой функции определяет смещение, на которое пользователь прокрутил колесико мыши. Оно передается в числовом виде в так называемых "тиках". Второй параметр передает ссылку на клип, над которым находился курсор мыши во время прокрутки ее колесика.

Для отслеживания координат мыши можно использовать свойства _xmouse и _ymouse объекта movieClip. Этот "нужный экземпляр" может быть как внешней анимацией (_root), так и каким-либо вложенным клипом. Эти же свойства поддерживаются и объектом Button.

 

Управление звуковым сопровождением фильма

Для управления звуковым сопровождением фильма служат экземпляры объекта sound. (О работе со звуком во Flash см. главу 17.) Эти экземпляры создаются с помощью выражений, имеющих следующий формат:

<Переменная> = new Sound( [<Клип, звуковым сопровождением которого нужно <управлять>] );

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

Вот два примера создания разных экземпляров объекта sound:

carSound = new Sound(car);

globalSound = new Sound();

Экземпляр carSound позволяет управлять звуковым сопровождением клипа саг, а экземпляр globalSound — всего фильма.

Объект sound имеет множество свойств и методов. В этом разделе мы рассмотрим некоторые из них.

Метод start запускает воспроизведение звука. Он имеет следующий формат вызова:

<Экземпляр объекта Sound>. start( [<Отметка>, <Количество повторов>]);

Этот метод может принимать два необязательных параметра. Первый параметр указывает, с какой отметки начнет воспроизводиться звук; отметка задается как количество секунд, которые Flash отсчитает с момента начала звука. Со вторым параметром передается количество повторов звука. Если ни один параметр не задан, звуковое сопровождение будет воспроизведено один раз с самого начала.

Например, выражение

carSound.start (10, 2);

запускает воспроизведение звука, привязанного к клипу car, с десятисекундной отметки и воспроизводит его два раза.

Метод stop немедленно останавливает воспроизведение звука. Формат его вызова таков:

<Экземпляр объекта Sound>. stop ([<Идентификатор образца-звука >]);

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

carSound.stop("engineSound");

Это выражение отключает воспроизведение звука engineSound, привязанного к клипу car.

Не принимающий параметров метод getVolume возвращает значение громкости звука. А метод setVolume позволяет задать новое значение громкости звука, переданное в качестве его единственного параметра. Доступны значения от 0 (звук не слышен) до 100 (полная громкость; значение по умолчанию).

carSound.setVolume(mySound.getVolume() + 10);

Это выражение увеличивает громкость работы автомобиля на десять единиц.

Пара методов get Pan и set Pan ведут себя так же и позволяют задать панорамирование звука в пространстве. Здесь доступны значения от -100 (звук в левом канале) до 100 (звук в правом канале); значение по умолчанию — 0 (звук "посередине").

carSound.setPan(50);

Объект sound также поддерживает два свойства, доступные только для чтения. Свойство position возвращает текущую воспроизводимую позицию звука в миллисекундах. А свойство duration возвращает общую продолжительность звука, также в миллисекундах.

 

Использование таймеров

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

Таймер создается с помощью действия setinterval. Оно имеет два формата вызова. Вот первый из них:

<Переменная> = setinterval (<Функция>, <Значение интервала>

[, <Список параметров функции, разделенных запятыми >]);

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

А вот второй формат вызова действия setinterval:

<Переменная> = setintervai(< Экземпляр объекта>, <Метод объекта>,

<Значение интервала>

[, <Список параметров метода, разделенных запятыми>]);

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

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

Приведем примеры выражений, создающих таймеры:

timerlDl = setintervai(tick, 1000);

timerID2 = setintervai(car, moveBy, 100, d);

Первое выражение создает таймер, вызывающий функцию tick каждую секунду (1000 миллисекунд). Второе же создает таймер, вызывающий каждые 100 миллисекунд метод moveBy экземпляра объекта car и передающий ему параметр d. Разумеется, и функция tick, и метод moveBy должны быть объявлены прежде, чем будут использованы.

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

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

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

clearinterval( <Идентификатор таймера>) ;

Например:

clearinterval(timerID2);

А теперь рассмотрим пример, показывающий, как можно использовать таймер для создания так называемого "ленивого" курсора мыши. Обычный курсор мыши нигде надолго не задерживается — он спешит за ней сразу после малейшего ее перемещения. "Ленивый" же курсор отличается от обычного тем, что никогда не торопится за мышью. Давайте же сделаем такой курсор.

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

Теперь напишем код сценария, который будет привязан к первому кадру фильма. Давайте рассмотрим его по частям.

function tick() {

if (_root.cursor._x!= _root._xmouse) {

if (_root.cursor._x < _root._xmouse) {

if (_root._xmouse — _root.cursor._x < d) {

_root.cursor._x = _root._xmouse;

} else {

_root.cursor._x += d;

}

} else {

if (_root.cursor._x — _root._xmouse < d) {

_root.cursor._x = _root._xmouse;

} else {

_root.cursor._x — = d;

}

}

}

if (_root.cursor._y!= _root._ymouse) {

if (_root.cursor._y < _root._ymouse) {

if (_root._ymouse — _root.cursor._y < d) {

_root.cursor._y = _root._ymouse;

} else {

_root.cursor._y += d;

}

} else {

if (_root.cursor._y — _root._ymouse < d) {

_root.cursor._y = _root._ymouse;

} else {

_root.cursor._у — = d;

}

}

}

updateAfterEvent();

}

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

Продолжаем писать наш сценарий:

d = 25;

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

ctID = setlnterval(tick, 50);

Здесь мы создаем таймер, вызывающий функцию tick каждые 50 миллисекунд.

И, наконец:

_root.onUnload = function() {

clearinterval(ctID);

}

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

Если уж зашла речь о таймерах, то нам может пригодиться функция getTimer. Она возвращает количество миллисекунд, прошедших с момента, когда фильм начал воспроизводиться.

 

Загрузка внешних файлов

 

Ранее в этой главе уже упоминалось о том, что язык ActionScript позволяет загрузить и поместить в фильм Flash внешний файл. Этим внешним файлом может быть другой фильм Shockwave/Flash, изображение в формате JPEG, видео Macromedia Flash Video или звук. Также имеется возможность открыть Web-обозреватель и загрузить в него какую-либо Web-страницу. Настала пора выяснить, как это делается.

 

Загрузка и выгрузка фильмов Shockwave/Flash и изображений в формате JPEG

Проще всего загрузить в основной фильм, воспроизводящийся в окне проигрывателя Flash, другой фильм Shockwave/Flash или изображение в формате JPEG из внешнего файла (загружаемого фильма). Такое часто делается, особенно при создании Web-сайтов, целиком основанных на Flash.

Вложение загружаемого фильма или изображения в основной фильм

Проще всего создать на рабочем листе "пустой" клип (например, с помощью метода createEmptyMovieClip, описанного ранее в этой главе) и заменить его загружаемым фильмом. При этом загружаемый фильм вкладывается в основной, становясь его составной частью.

Для загрузки фильма Shockwave/Flash или изображения JPEG из внешнего файла используется действие loadMovie, которое вызывается так:

loadMovie ("<Интернет-адрес внешнего файла >",

<Путь заменяемого клипа>) ;

Примеры использования действия loadMovie:

loadMovie("/images/truckWheel.swf", _root.car.wheel2);

loadMovie(sURL, _root.car);

Также можно воспользоваться методом loadMovie объекта movieClip. Формат его вызова почти такой же, как у одноименного действия:

<Заменяемый клип>. loadMovie ("<Интернет-адрес внешнего файла>") ;

Пример использования этого метода:

_root.car.wheel2.loadMovie("/images/truckWheel.swf");

Здесь мы загружаем фильм truckWheel.swf и заменяем им второе колесо нашего автомобиля.

А теперь предположим, что фильм truckWheel.swf из вышеприведенного примера содержит в себе сценарий:

_root.stop();

останавливающий воспроизведение его анимации (вращение колеса). Если открыть этот фильм в проигрывателе Flash, то сценарий выполнится правильно. Но если загрузить фильм truckWheel.swf в другой (основной) фильм, как мы это только что сделали, этот сценарий остановит анимацию не колеса автомобиля, а основного фильма. Ведь модификатор _root всегда возвращает ссылку на внешнюю анимацию, и в нашем случае он вернет ссылку на основной фильм, поскольку фильм truckWheel.swf стал его составной частью.

Что делать? Как нам заставить этот сценарий вложенного фильма выполняться корректно в любом случае? Очень просто: нужно привязать к первому кадру фильма truckWheel.swf вот такой совсем небольшой сценарий:

this._lockroot = true;

Здесь мы присвоили свойству _lockroot объекта movieClip, обозначающего сам фильм, значение true. После этого модификатор _root в любом сценарии, содержащемся в загружаемом фильме, всегда будет возвращать ссылку на внешнюю анимацию именно этого фильма — truckWheel.swf, даже если мы вложим его в другой фильм.

После того как нужда в загруженном из внешнего файла фильме или изображении пропадет, самое время его выгрузить. Зачем это нужно? Хотя бы затем, чтобы освободить ресурсы компьютера пользователя для других, более важных задач. Именно для этого язык ActionScript предоставляет действие unloadMovie, выгружающее из памяти и удаляющее с экрана ранее загруженный фильм. Формат вызова этого действия такой:

unloadMovie(<Путь выгружаемого клипа или изображения>);

Пример:

unloadMovie(_root.car.engine);

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

А вот это выражение выгрузит сам основной фильм:

unloadMovie(_level0._root);

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

Перекрывающиеся фильмы

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

Зачем может понадобиться перекрытие фильмов? А, например, для создания Web-сайтов, основанных на Flash. В этом случае сначала загружается и выводится на экран "объединяющий" фильм, содержащий заголовок сайта, полосу навигации и какой-то изначальный текст. При щелчке на какой-либо кнопке полосы навигации особый сценарий загружает фильм с соответствующим содержимым и выводит его на экран как перекрывающийся клип, перекрывая изначальное содержимое. Схема достаточно простая и наглядная; удивительно только, почему таких сайтов все еще довольно мало.

В главе 4, описывающей трансформации, давалось понятие порядка перекрытия фрагментов графики друг относительно друга (его еще называют z-координатой). В случае с перекрывающимися фильмами используется примерно такое же понятие, только называемое по-другому, а именно — уровень фильма. Отсчет уровней ведется, начиная с самого нижнего клипа (фильма) до самого верхнего. Фильмы с бо льшим номером уровня находятся "выше" фильмов с меньшим номером и перекрывают их.

На этом сходство с порядком перекрытия исчерпывается, и начинаются отличия. Их три.

Во-первых, самым "нижним" всегда является фильм, изначально воспроизводящийся в проигрывателе Flash, — он имеет уровень 0. Все остальные фильмы, которые будут загружены как перекрывающиеся, находятся "выше" него, т. е. имеют более высокий уровень — 1, 2 и т. д.

Во-вторых, для обозначения уровня фильма используются не числа, а особые модификаторы, в состав которых входят номера уровней. Они возвращают ссылку на внешнюю анимацию соответствующего фильма и имеют вид _level < номер уровня>. Самый "нижний" фильм имеет модификатор _level0. Более "высокие" фильмы имеют модификаторы _level1, _level2 и т. д.

Мы можем использовать эти модификаторы для доступа к перекрывающимся фильмам. Например:

_level0.gotoAndPlay(1);

_levell.car.wheel.stop();

Внимание!

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

В-третьих, мы можем загрузить какой-либо фильм на уровень, на котором уже имеется другой фильм. В этом случае загружаемый фильм заменит тот, что раньше был на этом уровне. Можно загрузить какой-либо фильм и на уровень 0 — в этом случае он заменит фильм, изначально загруженный в проигрыватель Flash.

Для загрузки перекрывающегося фильма используется действие loadMovieNum, аналогичное действию loadMovie. Формат его вызова таков:

loadMovieNum ("<Интернет-адрес загружаемого файла>", <Уровень >);

Приведем два примера выражений, использующих действие loadMovieNum:

loadMovieNum("/videos/driving.swf", 0);

loadMovieNum("/images/ads/banner45.jpg", 2);

Первое выражение заменяет основной фильм фильмом driving.swf. Второе же выражение загружает рекламный баннер и помещает его над основным фильмом. (Непонятно, правда, зачем это нужно делать. Если только для испытания нервов зрителей.)

Для выгрузки перекрывающегося фильма используется действие unloadMovieClip. Вот формат его вызова:

unloadMovieNum (<Уровень выгружаемого клипа или изображения >);

Пример:

unloadMovieNum(_level2);

Это выражение убирает назойливо маячивший перед глазами рекламный баннер.

 

Загрузка звуков

Для загрузки звука из внешнего файла в формате MP3 (другие форматы не поддерживаются) следует воспользоваться методом loadSound объекта Sound. Вот формат его вызова:

<Звук>. loadSound (<Интернет-адрес или путь внешнего звукового файла>,<Потоковый звук>);

Первый параметр задает интернет-адрес звукового файла или его путь на локальном диске компьютера в строковом виде. Второй параметр — логический — задает, будет ли загружаемый звук потоковым (значение true) или звуком-сигналом (значение false). (О потоковых звуках и сигналах см. главу 17.)

Вот пример сценария, загружающего звуковой файл с использованием метода loadSound:

newSound = new Sound();

newSound.loadSound("sounds/background_music.mp3", true);

newSound.play();

Объект Sound поддерживает событие onLoad, возникающее по окончании загрузки звука. Это событие можно обработать с помощью функции-обработчика, принимающей единственный параметр. Если звук был успешно загружен, этот параметр примет логическое значение true. Соответственно, если проигрыватель Flash почему-то не смог загрузить этот звук, обработчику передается значение false.

Вот пример функции-обработчика события onLoad:

function onNewSoundLoad(success) {

if (success) {

newSound.play();

}

}

newSound.onLoad = onNewSoundLoad;

Файлы формата MP3, кроме собственно звука, могут хранить дополнительные данные — так называемые теги MP3. В этих тегах записываются, в частности, имя исполнителя, название альбома и песни, год выпуска, жанр и пр. Для доступа к этим тегам служит свойство ID3 объекта Sound. Оно возвращает ссылку на экземпляр объекта Object, свойства которого и содержат информацию о различных тегах MP3. Эти свойства возвращают, в частности:

□ свойство ТСОМ — имя исполнителя;

□ свойство TALB — название альбома;

□ свойство TIT2 — название произведения;

□ свойство ТСОМ — жанр произведения;

□ свойство TYER — год выпуска альбома;

□ свойство TIME — продолжительность произведения;

□ свойство TRCK — номер произведения в альбоме.

Объект Sound поддерживает также методы getBytesLoaded и getBytesTotal, возвращающие соответственно размер загруженной части звукового файла в байтах и общий размер загружаемого звука в байтах.

 

Загрузка видео

Теперь рассмотрим процесс загрузки и воспроизведения внешних видеофайлов формата Macromedia Flash Video (другие форматы не поддерживаются). Подробно об этом формате было рассказано в главе 16.

Все находящиеся на рабочем листе экземпляры образцов-импортированных клипов, для которых было задано имя, представляют собой экземпляры объекта Video. Их создает сам Flash; нам же остается только использовать их свойства и методы.

Объект Video поддерживает метод attachVideo, выполняющий загрузку внешнего видеофайла и воспроизведение его в экземпляре образца-импортированного видео. Для загрузки и воспроизведения лучше всего использовать "пустой" видеоклип, процесс создания которого мы сейчас рассмотрим.

Итак, чтобы загрузить и воспроизвести внешний видеоклип, нужно сначала создать на рабочем листе "пустой" экземпляр объекта Video. Для этого откроем панель Library и выберем в ее дополнительном меню пункт New Video. В списке панели Library появится новый пункт с именем вида Embedded Video <порядковый номер>. Дважды щелкнем на этом имени, введем в появившееся поле ввода новое, более вразумительное имя и нажмем клавишу . Поместим на рабочий лист экземпляр этого образца и дадим ему какое-нибудь имя, например, vidExternal. Все — "пустой" видеоклип создан.

Теперь привяжем к первому кадру анимации такой сценарий:

var nc = new NetConnection();

nc.connect(null);

var ns = new NetStream(nc);

vidExternai.attachVideo(ns);

ns.play("videos/introduction.flv");

Здесь мы используем для загрузки внешнего видеофайла экземпляры объектов NetConnection и NetScream. Подробное описание этих объектов можно найти в интерактивной справке Flash.

 

Загрузка Web-страниц

Напоследок мы рассмотрим используемый во Flash способ загрузки в окно Web-обозревателя какой-либо Web-страницы. Для этого предназначено действие getURL, формат вызова которого таков:

getURL ( "<Интернет-адрес Web-страницы>" [, "<Цель>"] );

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

□ "_blank" — Web-страница загрузится в отдельное окно Web-обозревателя;

□ "_parent" — Web-страница загрузится в родительский набор фреймов;

□ "_seif" — Web-страница загрузится в текущий фрейм (это значение параметра по умолчанию);

□ "_top" — Web-страница загрузится в текущее окно Web-обозревателя, заменив собой весь набор фреймов, если он есть.

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

Вот пример сценария, привязанного к кнопке и загружающего Web-страницу сайта Macromedia в отдельное окно Web-обозревателя:

on (click) {

getURL("http://www.macromedia.com", "_blank");

}

 

Ограничения на доступ к внешним файлам

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

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

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

Какие же внешние файлы можно "трогать руками"? Какие ограничения Flash накладывает на доступ к внешним файлам? А вот какие…

Прежде всего, файлы, которые желают "общаться" друг с другом на уровне сценариев, должны быть загружены с одного и того же Web-сервера. А именно, если они были загружены с Web-сервера, имеющего IР-адрес 192.168.1.10, то они смогут обращаться к объектам, функциям и переменным друг друга. То же самое справедливо для файлов, загруженных с сервера . Однако если файлы были загружены с серверов и , то они не смогут "общаться" друг с другом на уровне сценариев.

Еще одно ограничение связано с протоколами HTTP (HyperText Transport Protocol, транспортный протокол передачи гипертекста) и HTTPS 5 (HyperText Transport Protocol Secured, защищенный транспортный протокол передачи гипертекста). (Протокол — это набор правил, согласно которым программы обмениваются данными по сети.) Если основной фильм был загружен по протоколу HTTP, а внешний — по протоколу HTTPS (или наоборот), то они не смогут получить доступ друг к другу через сценарии.

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

Пусть мы загрузили основной фильм с сервера . И пусть нам понадобилось загрузить с сервера внешний файл car.swf, поместить его на рабочий лист, а впоследствии иметь к нему доступ через сценарии. Для этого нам нужно будет использовать метод allowDomain объекта security, находящегося в объекте System. Формат его вызова таков:

System, security. allowDomain ("<Разрешенный интернет-адреc>") ;

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

В нашем случае нам нужно поместить в первый кадр анимации файла car.swf такой сценарий:

System.security.allowDomain("http://www.somesite.ru");

после чего все сценарии основного фильма, обращающиеся к файлу car.swf, будут работать.

Если основной фильм был загружен по протоколу HTTP, а внешний файл car.swf — по протоколу HTTPS, нам следует использовать метод allowinsecureDomain того же объекта. Формат вызова этого метода совпадает с форматом вызова метода allowDomain. А код необходимого сценария должен быть таким:

System.security.allowInsecureDomain("https://secured.somesite.ru");

_root.placeholder.loadMovie("https://secured.somesite.ru/car.swf");

Осталось заметить, что все вышесказанное относится только к файлам Shockwave/Flash. Для файлов Macromedia Flash Video и MP3 все это неактуально, так как они не содержат ни объектов, ни функций, не переменных, к которым можно получить доступ.

 

Работа с внешними данными

 

Загрузка и отображение на рабочем листе содержимого внешних файлов — это только часть возможностей, предлагаемых Flash для общения с внешним электронным миром. Другая, весьма обширная, часть позволяет получать и обрабатывать данные, поставляемые так называемыми серверными программами — программами, работающими совместно с Web-сервером. Сейчас мы об этом поговорим.

 

Отправка данных серверной программе

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

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

Для посылки данных нам следует использовать уже изученные методы и действия, а именно:

□ getURL — загрузка Web-страницы;

□ loadMovie и loadMovieNum — загрузка внешнего клипа;

□ loadSound — загрузка внешнего звука.

Поскольку серверная программа — это обычный файл, находящийся на диске компьютера, на котором работает Web-сервер (как и Web-страница), формат вызова всех этих действий и методов не изменится. Есть, правда, единственное исключение, о котором мы сейчас поговорим.

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

Первый способ передачи данных называется get. При его использовании данные передаются Web-обозревателем Web-серверу как часть интернет-адреса. Чтобы передать данные этим способом, нам нужно будет передать с последним параметром описанным выше действиям и методам значение GET.

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

name1 = Ivan

name2 = Ivanov

password = vanyusha

Тогда, чтобы отправить серверной программе program.exe, находящейся по адресу http://www.site.ru/bin/, эти данные методом get, мы напишем такое выражение:

getURL("http://www.site.ru/bin/program.exe", "_blank", "GET");

Обратим внимание на последний параметр этого метода. В нем передается строка "GET" — знак того, что данные должны быть переданы методом GET.

В результате Flash отправит Web-cepeepy следующий адрес (сами данные в нем выделены полужирным шрифтом):

http://www.site.ru/bin/program.exe ?name1=Ivan&&name2=Ivanov&password=vanyusha

Как видим, пересылаемые способом GET данные объединяются в пары "переменная" = "значение", помещаются в самый конец интернет-адреса и отделяются от него вопросительным знаком. При этом одна пара от другой отделяется знаком "коммерческое и" (&). Все это достаточно просто и наглядно.

Получив этот запрос, Web-cepeep первым делом отделит отправленные данные от собственно интернет-адреса серверной программы (в нашем случае это program.exe). Далее он запустит саму эту программу (если она еще не запущена) и передаст ей данные.

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

Чтобы реализовать способ POST, нам нужно будет передать соответствующему действию или методу с последним параметром строку "POST":

_root.loadMovie("http://www.site.ru/bin/getswf.exe", "POST");

Это выражение выполнит отправку данных способом post. В результате его выполнения серверная программа вернет файл Shockwave/Flash, содержащий клип, который заменит в окне проигрывателя Flash основной фильм.

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

 

Получение данных от серверной программы

Самый простой способ передать серверной программе данные и сразу же получить от нее результат их обработки — использовать действие loadVariabies или одноименный метод объекта movieClip. Это действие (метод) отправляет данные серверной программе и сразу же начинает ожидать получения результата. В принципе, с его помощью мы можем заставить приложение Flash загружать данные из текстового файла, находящегося на сервере или даже на диске нашего собственного компьютера.

Нужно сразу сказать, что серверная программа должна отправить данные, полученные в результате обработки, в виде строки, содержащей набор пар "переменная" = "значение", отделенных друг от друга знаком & (так же кодируются данные, передаваемые способом GET). Только тогда действие (метод) loadVariabies сможет правильно их обработать.

Получив от серверной программы данные, действие (метод) loadVariabies создает в указанном нами клипе соответствующие переменные, если они еще не созданы, и присваивает им принятые значения.

Формат вызова действия loadVariabies таков:

loadVariabies ("Интернет-адрес серверной программы",

Путь клипа, получающего данные "[, "GET|POST"]);

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

Примеры использования действия loadVariabies:

loadVariabies(" http://site.ru/bin/program.pi ", _root.dataHandler,"POST");

loadVariabies("data.txt", _root.dataHandler);

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

Метод loadVariabies вызывается почти так же:

<Клип, получаюпщй данные> .loadvariabies ("Интернет-адрес серверной программы" [, "GET | POST"]);

Например:

_root.dataHandler.loadvariabies(" http://site.ru/bin/program.pi ", "POST");

Для загрузки данных в перекрывающийся фильм используется действие loadVariablesNum. Вот формат его вызова

loadvariabies ("Интернет-адрес серверной программы",

"Уровень перекрытия фильма, принимающего данные" [, "GET|POST"]);

Комментарии, как говорится, излишни.

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

_root.loadVariables(" http://site.ru/bin/program.exe ");

_root.gotoAndStop(frameNumber);

Будет ли работать этот код? Может, будет, а может, и нет. И вот почему…

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

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

С учетом сказанного перепишем приведенный выше сценарий:

_root.onData = function() {

_root.gotoAndStop(frameNumber);

}

_root.loadVariables(" http://site.ru/bin/program.exe ");

Вот теперь он будет работать.

 

Использование объекта LoadVars

Существует другой способ получения данных от серверной программы — использование экземпляров объекта LoadVars. Этот объект предоставляет по сравнению с действиями loadVariable и loadVariableNum возможность несколько более строгого контроля над процессом обмена данными, хотя выполняет те же самые функции.

Прежде всего, нам нужно создать экземпляр объекта LoadVars:

myLoadVars = new LoadVars();

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

И разумеется, присваиваем этим свойствам нужные значения:

myLoadVars.namel = "Ivan";

myLoadVars.name2 = "Ivanov";

myLoadVars.password = "vanyusha";

Чтобы отправить данные серверной программе, используется метод send. Формат его вызова таков:

<Экземпляр объекта LoadVars>. send( "<Интернет-адрес серверной программы>" [, "<Цель>" , "GET|POST"]);

С первым параметром передается интернет-адрес серверной программы, которой посылаются эти данные. Со вторым параметром может быть передана цель, указывающая, куда будет выведен результат обработки этих данных (как правило, это Web-страница, сгенерированная серверным приложением). Третий необязательный параметр определяет способ отправки данных; если он не указан, выбирается способ POST.

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

myLoadVars.send(" http://site.ru/bin/program.exe ", "_blank", "GET");

Для приема данных от серверной программы используется метод load. С единственным параметром этого метода передается интернет-адрес этой серверной программы или же путь к текстовому файлу, содержащему нужные данные. Что касается данных, то они, опять же, должны быть представлены в виде текстовой строки, состоящей из пар "переменная" — "значение", отделенных друг от друга знаком &.

Вот пример использования метода load:

myLoadVars.load(" http://site.ru/bin/program.exe ");

Метод sendAndLoad одновременно отправляет серверной программе данные и получает от нее результат их обработки. Формат вызова этого метода:

<Экземпляр объекта LoadVars, отправляющий данные>. sendAndLoad ( "<Интернет-адрес серверной прогрраммы>" ,

<Экземпляр объекта LoadVars, принимающий данные> [, "GET | POST"]);

Этот метод вызывается для того экземпляра объекта LoadVars, который должен отправить данные. С первым параметром передается интернет-адрес серверной программы, которая должна их получить, со вторым — ссылка на экземпляр объекта LoadVars, который получит результат. Третий параметр определяет способ отправки данных; если он не указан, выбирается способ POST.

Например:

mySendVars.sendAndLoad(" http://site.ru/bin/program.exe ", myLoadVars);

Для того чтобы узнать, получены ли данные, нужно обработать событие load объекта LoadVars, возникающее после получения всех данных. Функция-обработчик этого события должна принимать один логический параметр, обозначающий, успешно ли получены данные (значение true) или нет (false).

Вот пример функции-обработчика этого события:

myLoadVars.onLoad = function(isSucceed) {

if (isSucceed) {

_root.gotoAndStop(frameNumber);

}

}

Свойство loaded объекта LoadVars возвращает значение true, если данные были успешно получены, и false в противном случае. Если операция приема данных не была запущена, возвращается значение undefined.

Объект LoadVars предоставляет также еще два метода, которые можно использовать для отображения процесса загрузки данных. Метод getBytesLoaded возвращает количество загруженных байт данных. А метод getBytesTotal возвращает общий объем загружаемых данных в байтах. Оба эти метода возвращают значение undefined, если операция загрузки данных не была запущена или еще реально не началась. Метод getBytesTotal также возвращает значение undefined, если Web-сервер, под управлением которого работает серверная программа, не сообщил размер передаваемых данных.

 

Что дальше?

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

Следующая глава будет посвящена оптимизации готовых изображений и фильмов перед их публикацией в формат Shockwave/Flash. Она совсем короткая.