Иллюстрированный самоучитель по Flash-games
Динамический текст После того
Рисунок 1.13 Панель Properties показывает параметры динамического текстового окна
В выпалаюшем меню имеется возможность выбрать расположение текста в одну строку (Single Line), в несколько строк (Multiline) и в несколько строк без возможности переноса (Multiline No Wrap). Кроме того, справа имеются три небольшие кнопки с опциями Selectable (Выделяемый), Render Text as HTML (Читать HTML-тэги) и Show Border Around (Показывать рамку вокруг текста). Опция HTML дает возможность использовать в тексте некоторые базовые тэги языка HTML, наподобие . Опция Border помешает текст в рамку и делает окно непрозрачным. Опция Selectable позволяет пользователю выделять блоки текста подобно тому, как это делается в текстовом редакторе.
Наиболее важной для программиста на ActionScript опцией данной панели является текстовое окно Var (Переменная), в которое вы можете ввести имя переменной. При воспроизведении ролика переменная и окно динамического текста будут связаны. При изменении значения одного из них соответственно будет меняться и значение второго. Это позволяет изменить переменную в программе и одновременно видеть эти изменения на экране.
В нижней части панели находится ряд кнопок, а также поле, где вы можете указать, начертания каких символов должны сохраняться в конечном. Flash-файле для дальнейшего использования в текстовом окне. Например, вы можете задать, чтобы вместо полного набора символов Hash сохранял вместе с роликом только цифры. С другой стороны, вы можете не сохранять вообше никаких наборов символов, тогда в текстовом окне будут использоваться только шрифты, установленные на компьютере пользователя.
Flash - достаточно умная программа и никогда не включает в swf-файл более одной копии каждого набора символов. Поэтому, если вы создали две области динамического текста, использующие все символы шрифта Arial, этот шрифт сохраняется только один раз и будет совместно использоваться обеими областями.
Главное окно Flash
Основой интерфейса Flash является главное окно и его важнейший элемент- рабочее поле. На рис 1.1 показано рабочее поле, которое содержит изображение большого дерева и лисы, держащей корзину.

Рисунок 1.1 Главное окно - основной элемент интерфейса Flash.
Для программиста на ActionScript одни элементы главного окна более важны, чем другие. В верхней части расположена временная шкала, в которой некоторые кадры помечены номерами 1, 5, 10 и 15. Сбоку временной шкалы находится панель управления слоями. В данном примере показаны два слоя: «Background» (Фон) и «Fox» (Лиса). Вы наверняка заметили, что кадры на временной шкале намного шире, чем обычно. Это связано с тем, что поле представления кадров было расширено при помощи кнопки Frame view (Отображение кадра), показанной на рис. 1.1. Существует еше несколько опций по управлению представлением кадров, например можно регулировать высоту каждого слоя (находится в свойствах слоя). Поэкспериментируйте с ними самостоятельно. Область рабочего поля главного окна может содержать любой элемент вашего ролика: графический образ, кнопку или клип. Изображение, показанное на рабочем поле главного окна, можно увеличить или сжать. Для этих целей предназначено всплывающее меню Scale (Масштаб), расположенное в левом нижнем углу главного окна, но для изменения масштаба намного удобнее пользоваться «горячими» клавишами. Нажатие клавиш Cntrl+2(PC) или Command+2(Mac) масштабирует рабочее поле так, чтобы оно вплотную занимало все свободное место в главном окне. Использование сочетания клавиш Cntr+3 или, соответственно, Command+З масштабирует рабочее поле так, что в главном окне максимально распахивается область, содержащая все изображения, в том числе те, которые находятся на серой области вне пределов рабочего поля. Сочетание Cntrl+1 (Command+1) возвращает рабочему полю масштаб 100%. И наконец, использование командных клавиш в сочетании с + и - позволяет изменять текущий масштаб в два раза. Последнее, о чем хотелось бы здесь сказать, - кнопки Show/Hide (Показать/Скрыть) и Lock/Unlock (Заблокировать/Разблокировать). Эти функции чрезвычайно полезны тем, что позволяют отобразить отдельные слои или определенный набор слоев. Блокировка слоев позволяет без труда выбрать нужный вам объект, не внеся при этом случайных изменений в другой слой.
Импорт мультимедийных элементов во Flash
Хотя основой Flash является векторная графика, программа может использовать и другие элементы, например растровые изображения и звуковые файлы. Flash не позволяет редактировать эти элементы, они только отображаются. Создавать растровые изображения и звуки следует в других программах, например Adobe Photoshop и Sound Forge. Давайте рассмотрим эти два типа элементов и способы их- использования с помошью ActionScript.
Интерфейс Flash.
Прежде чем создавать сложные программы на ActionScript, вам необходимо хорошо изучить интерфейс Flash, который включает множество окон, панелей и меню.
в ролике необходима профаммисту на
Маркировка кадров в ролике необходима профаммисту на ActionScript для того, чтобы задать в программе нелинейный переход ролика с одного кадра на другой. Присвоить имена кадрам можно в панели Properties.
В ActionScript имеется возможность ссылаться на номера кадров, однако мы не советуем этого делать. Почему? Предположим, вы написали программу, задающую переход от кадра 7 на кадр 13, а затем на кадр 8. После этого решили добавить кадр перед кадром 1. Кадры, которые раньше имели номера 7, 13 и 8, получат номера 8, 14 и 9, и вам придется менять программу в трех местах.
Присвоив кадрам имена, вы можете ссылаться на эти имена в программе. При этом вне зависимости от количества добавленных и удаленных кадров вы всегда будете уверены, что ключевой кадр сохранил свое имя.
Меню Control
Меню Control (Управление) включает постоянно используемую команду Test Movie (Пробное воспроизведение ролика). Данная команда, выполняемая также нажатием клавиш быстрого доступа Command+Return (Macintosh) или Ctri+Enter (Windows), преобразует ваш текущий ролик в конечный swf-файл и затем запускает его в окне предварительного просмотра. Ролик воспроизводится аналогично тому, как он бы воспроизводился в проигрывателе Flash или в Web-браузере пользователя. Данная команда отличается от команды Play (Воспроизведение) из меню Control, которая не использует никаких сценариев ActionScript, находящихся в ролике. Команда Play совершенно бесполезна для программиста, в то время как команда Test Movie бесценна.
Меню Edit
Меню Edit (Правка) включает обычные команды: Сору (Копировать), Cut (Вырезать) и Paste (Вставить). Команда Undo (Отменить) особенно полезна, так как с ее помощью вы можете отменить 100 последних действий, что является довольно значительной цифрой. Вы можете задать количество отменяемых действий, выбрав команду Edit -> Preferences (Правка -> Настройка). При выборе команды Preferences на экране появится диалоговое окно, показанное на рис. 1.7. Здесь вы можете не только указать число отменяемых действий, но и задать целый ряд настроек, упорядоченных в три отдельные вкладки. Что касается меня, я стараюсь придерживаться настроек по умолчанию, однако никогда не помешает знать, какие опции вам предлагаются. Обычно я меняю предлагаемый по умолчанию режим Normal (Обычный) на режим Expert (Эксперт), что позволяет мне набирать команды ActionScript непосредственно в окне редактирования сценария.

Рисунок 1.7 Для того чтобы вызвать диалоговое окно Preferences, используйте основное меню, но его расположение зависит от вашей операционной системы
Меню File
Меню File (Файл) включает стандартный набор команд, знакомый пользователям Macintosh и Windows. Наряду с командами Open (Открыть), Save (Сохранить) и Save As (Сохранить как) здесь присутствует также команда Import (Импорт), позволяющая импортировать в программу растровые изображения, векторную графику и звуковые файлы. Наиболее важной в меню File является простая команда Save, которой соответствует сочетание клавиш Command+S (Macintosh) и Ctrl+S (Windows). Советуем вам почаще ее использовать. Если после многочасовой работы без сохранения программа или компьютер дадут сбой, вы пожалеете о том, что не нажимали данное сочетание клавиш каждые пять минут.
К сожалению, Flash время от времени имеет обыкновение давать сбой, что приводит к потере всей вашей работы со времени последнего сохранения. Компания Macromedia регулярно поставляет новые, исправленные и усовершенствованные версии flash. Обратной стороной такого стремительного развития программы является ее нестабильность. Тем не менее, если вы не будете забывать почаще сохранять вашу работу, возникающие сбои не испортят вам настроения.
В меню File также находятся команды Publish (Публикация) и Publish Settings (Параметры публикации). Подробнее об этих командах вы узнаете в конце данной главы.
Меню Insert
Меню Insert (Вставка) содержит две функции, полезные для программиста на ActionScript. Первая из них - команда Convert to Symbol (Преобразовать в символ), которая преобразует выделенные вами элементы в графический объект, клип или кнопку. Вновь созданный эталон включается в библиотеку, а также остается на рабочем поле, на месте исходных элементов. При вызове данной команды на экране появляется диалоговое окно Symbol Properties (Свойства символа), в котором вы должны задать тип символа и назначить ему имя (рис. 1.9).

Рисунок 1.9 Диалоговое окно Symbol Properties появляется на экране при выборе команды Insert -> Convert to Symbol. Это же окно появится, если вы захотите изменить свойства уже существующего символа.
Команда Convert to Symbol позволяет создавать графические объекты, клипы и кнопки непосредственно на рабочем поле и затем добавлять их в библиотеку. Вы также можете использовать эту команду для создания символов внутри символов. Например, вы можете создать объект, похожий на кнопку, при помощи команды Convert to Symbol превратить его в кнопку, а затем, повторно используя данную команду, поместить кнопку в клип. Второй важной функцией меню Insert является набор команд, позволяющих добавлять кадры в главную временную шкалу. Чтобы добавить новый кадр, используйте команду Insert -> Frame (Вставить -> Кадр). Для добавления нового ключевого кадра во временную шкалу предназначены команды Insert -> Keyframe (Вставить -> Ключевой кадр) и Insert -> Blank Keyframe (Вставить -> Пустой ключевой кадр). В первом случае будет создана копия текущего ключевого кадра, во втором - новый ключевой кадр, не содержащий никаких объектов на рабочем поле. При помощи команды Insert -> Remove Frames (Вставить -> Удалить кадры) можно удалить выбранные в слое кадры, а используя Insert -> Clear Keyframe (Вставить -> Очистить ключевой кадр), удалить ключевой кадр, не удаляя простых кадров слоя. Команды для работы с кадрами могут немного сбить с толку тех, кто никогда до этого не создавал анимации во Flash. Лучший способ научиться работать с этими командами - попробовать их применить. Создайте ролик и потренируйтесь добавлять и удалять кадры и ключевые кадры. Тогда вы начнете понимать, как работают эти команды.
Разница между кадром и ключевым кадром состоит в следующем: ключевой кадр - это точка временной шкалы, определяющая точное положение всех объектов на рабочем поле данного слоя. Они не будут менять своего положения до следующего ключевого кадра. Однако аниматоры могут выбрать, например, анимацию движения между ключевыми кадрами, при этом объекты рабочего поля будут постепенно передвигаться из позиции, определяемой первым ключевым кадром, к позиции, определяемой следующим ключевым кадром. Более подробно о ключевых кадрах вы узнаете из урока анимаиии, поставляемого с программой Flash MX.
Меню Modify
Меню Modify предоставит вам еще несколько способов быстрого доступа к панелям. Команда Modify -> Document открывает окно свойств документа (рис 1.10). Диалоговое окно Document Properties (Свойства документа) позволяет изменить размеры ролика, количество кадров в секунду и цвет фона.

Рисунок 1.10 В диалоговом окне Document Properties задаются наиболее важные свойства ролика
Также заслуживает упоминания набор команд подменю Transform (Трансформация). Эти команды служат для изменения масштаба, вращения и транспонирования графических объектов на рабочем поле. Далее в книге рассказано, как выполнять подобные действия при помощи ActionScript, но некоторыми графическими изображениями и символами невозможно управлять при помощи ActionScript, поэтому эти команды надо обязательно знать. Следует также остановиться на команде Group (Группировать). В случае наложения друг на друга графических объектов линии и заливка объекта, расположенного снизу, могут оказаться скрытыми. Например, если вы нарисуете большой синий круг, в центре этого круга нарисуете маленький красный круг, а затем удалите красный круг, то в центре первого круга, на том месте, где был расположен красный, получится дырка. Если же вы сгруппируете синий круг перед тем, как рисовать красный, то первый не окажется частично стертым, а останется в своем первоначальном виде под вторым.
Меню Text
Включенные сюда команды обеспечивают быстрый доступ к опциям панелей Text (Текст). Более подробно о работе с текстом мы расскажем в разделе "Создание текста" данной главы.
Меню View
Меню View (Вид) позволяет изменять масштаб отображения рабочего' поля и степень детализации отображаемых на нем графических элементов во время работы над роликом, а также использовать сетки и направляющие.
Сетка пригодится для быстрого выравнивания элементов на рабочем поле в том случае, если вам важнее составить программу на ActionScript, а не найти лучший способ расположения графических объектов. Чтобы вызвать диалоговое окно Grid (Сетка), показанное на рис. 1.8. надо выбрать команду View -> Grid -> Edit Grid (Вид -> Сетка -> Редактировать сетку). Здесь вы можете задать масштаб сетки и ее цвет, указать, будет ли сетка отображаться на экране, и будут ли к ней привязываться объекты. Диалоговое окно Grid позволяет быстрее задавать и отменять данные настройки, чем команды Show Grid (Показать сетку) и Snap To Grid (Привязать к сетке).

Рисунок 1.8 В диалоговом окне Grid задаются цвет и другие настройки сетки
Меню View включает команду Hide Panels (Скрыть панели), которую можно также выполнить простым нажатием на клавишу табуляции. При этом все панели, включая палитру Tools (Инструменты), будут моментально скрыты или отображены. Это удобно, если некоторые часто используемые панели закрывают рабочее поле, и вы хотите их скрыть, но так, чтобы в следующий раз они появлялись на том же самом месте экрана.
Меню Window
С помощью меню Window (Окно) вы можете открыть все панели, а также все другие окна. Сочетания клавиш для быстрого доступа к наиболее часто используемым инструментам приведены в таблице:
Нерабочая область
p
Существует одна область интерфейса Flash, чрезвычайно полезная программисту на ActionScript, однако редко упоминаемая в книгах, подобных этой. Это область, которая находится за пределами рабочего поля. Взгляните на рис. 1.1 и обратите внимание на серую область вокруг рабочего поля, расположенного в центре окна. В эту область вы можете помещать элементы. При воспроизведении ролика в браузере пользователя или в программе Flash Player данная область не будет видна.
В нерабочей области можно, например, разместить небольшой клип с написанным для него кодом ActionScript. В отличие от кода в главной временной шкале, выполняющегося один раз, ActionScript-код клипа будет выполняться в каждом кадре.
Вероятность того, что пользователь увидит нерабочую область, все же существует. Если изменение масштаба ролика выполняется во Flash Player, окне предварительного просмотра Flash или в браузере, ролик старается сохранить свои пропорции, и некоторые области, расположенные выше или ниже рабочего поля, могут быть видны. Этого не произойдет, если поместить ролик в Web-страницу, используя правильные тэги (об этом рассказывается ниже).
Таким образом, поместив небольшой клип за пределы рабочей области, где он не будет виден, вы можете создать код, выполняющий повторяв юшиеся действия, например анимацию или движение, контролируемое пользователем.
Окно справки
В окне Reference (Справка) содержится словарь ActionScript программы Flash. Даже самый опытный программист ActionScript не будет знать всех свойств, применений и отличительных особенностей синтаксической структуры Flash. Это меню позволит вам быстро получить необходимую информацию об определенной команде или функции.
Организация ролика
Процесс организации ролика более важен для программиста на Action Script, чем для Flash-аниматоров. Символам в библиотеке должны быть присвоены содержательные имена. При необходимости их надо систематизировать по каталогам. Слои на главной временной шкале должны обеспечивать легкий доступ к различным элементам рабочего поля.
Панели
Хотя главное окно программы Flash и является основным элементом, оно содержит очень мало подробной информации о вашем ролике и его частях. Детали отображаются в небольших окнах панелей управления. При запуске они появляются в правой и нижней частях главного окна, однако, затем их можно перемешать куда угодно.
Эти панели могут быть приведены к любому виду. Панели находятся каждая в своем окне, но можно отобразить сразу несколько из них в одном окне в виде закладок. Например, на рис. 1.2 показано окно, включающее панели Color Mixer (Миксер цветов), Color Swatches (Образцы цвета) и Components (Компоненты). Только панель Color Swatches доступна к использованию.

Рисунок 1.2 Это окно содержит три панели
Вы можете изменить состав окна панелей, а также создать новое окно. Это осуществляется перетаскиванием панелей за левую, помеченную характерной "дырчатой" текстурой, часть титульного поля панели. Для того чтобы научиться перемещать панели, требуется немного практики. У вас всегда есть возможность вернуть исходные настройки, выбрав команду Window -> Panel Sets -> Default Layout (Окно -> Наборы панелей -> Расположение по умолчанию).
Необязательно перемешать панели между окнами панелей только потому, что у вас имеется такая возможность. Я нахожу расположение по умолчанию самым лучшим вариантом, которого и придерживаюсь. Это также удобно, если вам придется работать на другом компьютере, в этом случае вам не надо будет привыкать к какому-либо нестандартному расположению. Вы можете сохранить собственную конфигурацию панелей с помощью команды Window -> Save Panel Layout. Сохраненные конфигурации доступны с помощью команды Window -> Panel Sets.
Панель Info, которую можно выбрать командой Window -> Info, необходима для точного размещения объектов на рабочем поле. Выбрав объект, вы можете задать значения его координат (X и Y), а также его ширину и высоту (W и Н). Панель Transform (рис. 1.3) можно выбрать командой Window -> Transform. Эта панель позволяет изменять масштаб выделенного объекта и поворачивать его.

Рисунок 1. 3 Панель Transform позволяет изменять масштаб выделенного объекта и поворачивать его
Еще одна панель, которую постоянно используют программисты на ActionScript, - Properties (Свойства). Эта панель (рис. 1.4) отображает информацию о выбранном в данный момент объекте: графическом символе, кнопке или клипе. С помощью этой панели вы можете менять различные свойства выбранных объектов. Например, ставить метки выделенным кадрам и присваивать имена клипам. Для того чтобы можно было программно обращаться к клипам, им необходимо присвоить имена.

Рисунок 1.4 Панель Properties позволяет присваивать имена клипам
Панель Properties (Свойства) позволяет присваивать имена (метки) кадрам. Как ни странно, вы можете сделать это в любом слое. Например, вы можете присвоить имя первому кадру, выделив его в верхнем слое, затем присвоить имя второму кадру, выделив его в следующем слое. Неправда ли, сбивает с толку? Я советую помечать все кадры в одном слое (обычно так и делают, называя этот слой, например, "labels"). Наиболее важным окном после рабочего поля как для программиста на ActionScript, так и для художника-графика, несомненно, является палитра Library (Библиотека). Панель на рис. 1.5 содержит растровое изображение, кнопку, папку, графический символ и клип.

Рисунок 1.5 Палитра Library показывает, из каких элементов состоит ваш ролик
Палитра Library показывает список различных элементов, составляющих ваш ролик. На первый взгляд элементы списка кажутся выбранными наугад. Например, графические образы, которые были нарисованы непосредственно на экране, не отображаются в палитре, даже если они были сгруппированы. Если же вы сохраните их как графический символ, они будут показаны. Логика здесь такая: библиотека хранит многократно используемые объекты. Любой символ, будь то клип, графический символ или кнопка, могут использоваться в одном или нескольких местах вашего ролика.Однако набор линий и заливок, нарисованных непосредственно на рабочем поле, может применяться только в кадре или наборе кадров на временной шкале. Включение эталона в библиотеку не означает, что он будет экспортирован вместе с роликом. Например, вы импортируете растровое изображение или звуковой файл, но не помешаете его на рабочее поле. Или же создаете клип и не используете его. В таком случае умная программа не включает этот объект в конечный, сжатый swf-файл, что способствует уменьшению размера файла и его быстрой загрузке. Что делать, если элемент библиотеки не выложен на рабочее поле, а ваша программа его использует? Flash не будет отслеживать это и не включит данный элемент в конечный файл ролика. Для того чтобы заставить Flash включить в конечный файл кажущийся ему ненужным элемент библиотеки, установите связь с этим элементом в диалоговом окне Symbol Linkage Properties (Свойства связи символа) - см. рис.1.6. Диалоговое окно можно вызвать из всплывающего меню Options (Параметры), расположенного в правом верхнем углу палитры Library (рис. 1.5).
Подготовка ролика к публикации
Независимо от того, является ли ваш ролик простой анимацией или сложным приложением, после окончания работы над ним его необходимо экспортировать в swf-файл. Это можно сделать при помощи команды File Publish (Файл -> Опубликовать).
Перед этим, однако, надо проверить определенные элементы ролика и, воспользовавшись командой File -> Publish Settings (Файл -> Настройки публикации), настроить его соответствующим образом.
Публикация
Перед тем как применить команду File -> Publish (Файл -> Публиковать), вызовите диалоговое окно Publish Settings (рис. 1.22). Это большое диалоговое окно состоит из трех вкладок. Вкладка Formats (Форматы) позволяет вам выбрать формат для экспорта. Однако форматы GIF, JPEG и PNG представляют собой неподвижные изображения, а форматы QuickTime Movie и RealPlayer не поддерживают ActionScript программы Flash 5 или MX.
Поэтому единственной реальной альтернативой остается формат SWF и Projectors. Вы также можете выбрать экспорт HTML-страницы, которая будет использоваться вместе с swf-файлом.

Рисунок 1.22 Диалоговое окно Publish Settings дает возможность экспортировать ролик Flash в одном из нескольких форматов
Вкладка Flash позволяет задать несколько настроек конечного swf-файла (рис. 1.23). При выборе опции Generate Size Report (Создать отчет о размере) программа создает краткое описание содержимого swf-файла и помешает его в окно Flash Output (Window => Output). Также создается отдельный файл отчета FileName Report.txt (где FiteName - имя вашего, fla-файла), который помешается в ту же директорию, что и fla-файл. Это поможет вам найти и сократить элементы, занимающие много места.

Рисунок 1.23 Вкладка Flash диалогового окна Publish Settings позволяет изменять некоторые важные настройки swf-файла
Опция Omit Trace Actions (Игнорировать трассировку) предназначена для того, чтобы отключать сообщения, выводимые командой trace в окно Output. Вывод сообщений происходит только при проигрывании фильма в редакторе, так что для просмотра в браузере или посредством Flash-плеера эта опция не существенна.
Опция Protect from Import (Зашита от импорта) создает защищенный от импорта фильм. При попытке импортировать такой ролик будет затребован пароль.
Опция Debugging Permitted (Разрешить устранение неполадок) позволяет вам устранять неполадки в ролике во время его воспроизведения. Более подробно об устранении неполадок рассказано в главе 4 "Процесс создания игры".
Следующий ряд настроек дает возможность установить значение сжатия по умолчанию для изображений и звуков. При установке флажка Override Sound Settings (Заменять настройки звука) все звуки будут сжаты с параметрами по умолчанию, независимо от ранее установленной степени сжатия.
Опция Version (Версия) в нижней части окна, похоже, может творить чудеса. Она предлагает сохранить ролик во Flash 1, 2, 3, 4 или 5. Получается, что создаваемые вами ролики со сложным сценарием ActionScript будут работать во Flash 3? Нет. Если ваш ролик содержит хоть какой-нибудь сценарий на ActionScript, скорее всего, его необходимо экспортировать как ролик Flash 5 или MX. Если же вы используете новые команды версии MX, то ничего не остается, кроме как импортировать фильм в этой версии.
Последняя вкладка диалогового окна Publish Settings, изображенная на рис. 1.24. позволяет задать внешний вид HTML-файла, экспортируемого с swf-файлом.

Рисунок 1.24 Вкладка HTML диалогового окна Publish Settings позволяет задавать настройки HTML-файла, экспортируемого с swf-файлом
На самом деле опции, показанные на рис. 1.24, не контролируют swf-файл, а только задают тэги HTML-страницы. Эти тэги мы рассмотрим в следующем разделе.
Учтите, что настройки Flash Alignment, теоретически позволяющие определять положение swf-файла на странице браузера, реально не работают ни во Flash MX, ни в более ранних версиях.
Пункты меню
Выбор пунктов меню столь же богат, как и выбор панелей. Однако регулярно используется лишь небольшая их часть. Программисту на ActionScript,помимо расположения самих пунктов меню, необходимо знать сочетания "горячих" клавиш для выполнения наиболее часто используемых команд.

Рисунок 1.6 В диалоговом окне Symbol Properties можно указать, что объект должен быть включен в библиотеку для последующего экспорта в Action Script.
Растровые изображения
ля импорта растровых изображений во Flash используйте команду File -> Import (Файл -> Импорт). Вы можете импортировать различные графические форматы, включая JPEG, GIF, PICT и BMP. Файл будет добавлен в библиотеку вашего ролика. После импорта изображения в библиотеку с ним мало что можно сделать при помоши ActionScript. Тем не менее вы можете поместить его в клип. Над изображением, импортированным во Flash, можно произвести не так уж много операций. На рис. 1.14 показано диалоговое окно Bitmap Properties (Свойства растрового изображения), вызываемое двойным щелчком мыши по изображению в библиотеке.

Рисунок 1.14 Диалоговое окно Bitmap Properties позволяет задавать степень сжатия растра, включить и отменить сглаживание и повторить импорт при помоши кнопки Update (Обновить)
Для того чтобы преобразовать растровое изображение в векторное, выделите его на рабочем поле и выберите команду Modify -> Trace Bitmap (Изменить -> Трассировать растр}. При этом на экране появится диалоговое окно, показанное на рис. 1.15.

Рисунок 1.15 В диалоговом окне Trace Bitmap осуществляется преобразование растрового изображения в векторное
Функция Trace Bitmap заменяет растровое изображение набором закрашенных векторных областей. В большинстве случаев это приводит к ухудшению качества рисунка по сравнению с исходным, но, по крайней мере, теперь его можно масштабировать аналогично векторному изображению.
Многие художники преобразуют растровое изображение в векторное на одном из этапов его создания. Например, можно нарисовать что-нибудь на бумаге, отсканировать изображение в файл, а затем трассировать полученный растр в векторное изображение. Многие художники используют для преобразования не Flash, а программы типа Adobe Streamline. Затем изображение импортируется во Flash. После этого художник должен довольно много потрудиться, чтобы изображение выглядело так, как было задумано.
Размещение Flash-ролика в сети
Для того чтобы поместить ролик в сети, его необходимо вставить в HTML-страницу. Конечно, вы можете поместить ролик как swf-файл, однако в этом случае он увеличится до размера окна браузера, что вам не нужно.
При помощи двух тэгов вы можете поместить swf-файл на Web-страницу и для Internet Explorer, и для Netscape, Более того, множество настроек позволяют задавать нужный внешний вид ролика. Большинство из них автоматически применяются программой при публикации и могут быть установлены в диалоговом окне Publish Settings, показанном на рис. 1.24. Тем не менее вам не помешает знать, как выглядят эти элементы. Не знаю, как вы, а я бы скорее предпочел создать свой собственный HTML, чем использовать шаблон Flash.
Приведенный ниже элемент содержит Flash-ролик размером 550x400 под названием Sample.swf. Воспроизведение ролика начинается сразу, уровень качества - высокий, используются шрифты устройства, фоновый цвет - белый.
Приведенный выше код исполняется отлично, однако создает одну проблему: почти каждый параметр должен повторяться дважды, один раз в элементе OBJECT, второй - в элементе EMBED. Если вы вносите какие-либо изменения, не забудьте сделать это в обоих тэгах.
Теперь, узнав, как связаны Flash и ActionScript, вы готовы стать программистом на ActionScript. В следующей главе мы начнем изучение Action-Script.
Сцены
Сцены являются более высоким уровнем организации роликов во Flash. Каждый Flash-ролик состоит из одной или нескольких сцен. В большинстве примеров, рассматриваемых в данной книге, используется лишь одна сцена, поэтому вы можете просто забыть об их существовании.
Тем не менее, сцены могут служить прекрасным организационным инструментом. Они представляют собой последовательное сочетание нескольких роликов, образующих одно целое. Каждая сцена имеет свою временную шкалу. На рис. 1.21 показана панель Scene (Сцена), которая включает три сцены. Они воспроизволятся точно в указанном порядке, хотя ActionScript может игнорировать его и воспроизводить сцены в любой последовательности и даже переходить с кадра одной сцены на кадр другой сцены.

Рисунок 1.21 Панель Scene позволяет создавать и по-разному организовывать сцены вашего ролика
Слои
Хотя в большинстве случаев программы, написанные на ActionScript, не манипулируют слоями, слои являются ценным инструментом для организации ролика. Вы можете и должны использовать разные слои для меток, кода ActionScript и графических объектов. На рис. 1.19 показан пример правильной организации ролика при помощи слоев.

Рисунок 1.19 Данное устройство временной шкалы включает один слой только для меток, еще один для ActionScript и остальные для графических объектов
Двойным щелчком мыши по небольшой пиктограмме слева от каждого слоя можно вызвать диалоговое окно Layer Properties (Свойства слоя) - см. рис. 1.20. Слою можно задать, например, свойство Outline (Контур), тогда все изображения данного слоя будут отображаться в виде контуров. Данный режим действует только в процессе работы в среде Flash; при просмотре swf-файла изображение примет обычный вид.

Рисунок 1.20 В диалоговом окне Layer Properties можно задать тип слоя
Применяйте слои для организации не только главной временной шкалы, но и клипов, графических изображений и кнопок.
Создание текста
Во Flash имеется три различных типа текстовых окон. Первое, статический текст, - если рассматривать его с точки зрения программиста на АсtionScript, - это не более чем графические объекты в форме текста. Другие два, динамический и редактируемый тексты, могут быть изменены при помощи ActionScript.
Список заключительных проверок
Вот список элементов, которые необходимо проверить перед публикацией ролика:
• имена копий клипов - имена всех клипов, помещенных на рабочее поле, должны совпадать с именами в коде;
• свойства связи - в случае, если клип не используется на рабочем поле, но используется кодом, необходимо настроить его свойства связи в библиотеке таким образом, чтобы он экспортировался с роликом. Имя связи должно соответствовать имени, которое используется в вашем коде. Все вышесказанное относится и к звуковым файлам, содержащимся в библиотеке;
• имя динамического текста - имя динамического текста, используемого на рабочем поле и связанного с переменной ActionScript, должно соответствовать вашему коду;
• шрифты - текстовое окно динамического или редактируемого тек ста должно содержать все символы, которые могут вам понадобиться. В противном случае при воспроизведении на машине, где установлены другие шрифты, текст будет искажен;
• команда stop - команду ActionScript stopo необходимо поместить во все кадры, с которыми может взаимодействовать пользователь. Кадр, не содержащий команды stop О, является не более чем отдельным кадром анимации. Это также относится к клипам вашего ролика. Если они контролируются ActionScript, их первый кадр должен содержать команду stop О. Более подробную информацию об этой команде вы найдете в главе 2 "Введение в ActionScript".
Свойства текста При выделении
Рисунок 1.12 Окно Properies позволяет изменять свойства текста
Звуки
Импорт звуковых файлов во Flash осуществляется способом, аналогичным импорту растровых изображений. Flash импортирует стандартные звуковые форматы: AIFF, МРЗ, Sun AU и Wave.
После того как файл импортирован во Flash, двойным щелчком мыши по его имени в библиотеке можно открыть диалоговое окно Sound Properties (Свойства звука) - см. рис. 1.16.

Рисунок 1.16 Диалоговое окно Sound Properties позволяет задавать степень сжатия звукового файла при включении его в конечный Flash-ролик
Обычно звуковые элементы перетаскивают на временную шкалу и помешают в ключевой кадр. Когда начинает воспроизводиться ключевой кадр, запускается воспроизведение соответствующего звукового файла. Параметры звукового файла, прикрепленного к кадру, можно настроить, вызвав соответствующую ему панель Sound (Звук).
Настройка степени сжатия звукового файла в диалоговом окне Sound Properties необходима в случае, если для вас важно качество звука в конечном ролике. Например, использование компрессии МРЗ со скоростью воспроизведения 16 Кб/с даст звук среднего качества, подходящий для специальных эффектов и т. п. Однако, если вы используете качественную музыку, вам понадобится скорость 32 Кб/с или даже 64 Кб/с. Советуем поэкспериментировать с различными настройками и подобрать их таким образом, чтобы получить звук хорошего качества и одновременно занимающий как можно меньше места. При сохранении ролика вы можете также установить настройки по умолчанию, которые будут применяться для всех звуков ролика.
Показанная на рис. 1.17 панель Properties позволяет установить способ запуска звукового файла, его повторение и даже применить эффект его постепенного исчезновения. Так как в нашу задачу не входит использование этих свойств звука, не будем рассказывать о них подробно.

Рисунок 1.17 Панель Properties служит для настройки звуковых файлов, находящихся на временной шкале
Вместо этого рассмотрим, как с помощью команд ActionScript запустить звуковой файл, а также настроить время и способ его воспроизведения.
В случае, если на временной шкале звук отсутствует, Flash не включит его в конечный файл, и попытка ActionScript запустить его не удастся.
Чтобы обеспечить включение звука в конечный файл, необходимо установить свойства связи (см. рис. 1.6). Для ссылок на звуковой файл в ActionScript следует использовать имя, назначенное данному файлу в диалоговом окне Linkage Properties.
Сценарии для кнопок
Вы также можете задавать сценарии для кнопок. Прежде всего вам следует создать кнопку как элемент библиотеки. Затем, если необходимо, перетащите кнопку на рабочее поле. Выделите ее и нажмите F9 для того, чтобы вызвать диалоговое окно Actions. В случае, если диалоговое окно уже на экране, шенарий кнопки будет отображен при ее выделении.
Теперь окно Actions имеет заголовок Actions - Button (Действия - Кнопка). Любой сценарий, введенный здесь, будет выполнен кнопкой. Однако вы не можете просто ввести набор команд. Вы должны запрограммировать реакцию кнопки на выполнение различных событий, например на ее нажатие, помещение над ней курсора и т.д. Код, обрабатывающий подобные события, называется программой-обработчиком. Сценарий кнопки представляет собой набор из одного или нескольких обработчиков.
Сценарии кадра
Вы можете помешать сценарии в ключевые кадры главной временной шкалы вашего ролика. Для этого выделите ключевой кадр на главной временной шкале и нажмите F9. На экране появится диалоговое окно Actions - Frame (Действия - Кадр).
Сценарии кадра могут содержать два типа элементов. Первый - это набор команд, исполняемых при воспроизведении кадра ролика. Команды исполняются друг за другом, пока не будет достигнут конец сценария.
Вторым типом элемента, включаемого в кадровый сценарий, является функция. Функции - это элементы кода, которые могут быть многократно использованы командами в сценариях кадра, а также другими сценариями ролика.
Сценарии клипов
Вы также можете назначить сценарий клипу. Для этого прежде всего создайте клип и сохраните его как элемент библиотеки. Затем поместите копию клипа на рабочее поле. Выделив копию клипа на рабочем поле, вызовите окно Actions, оно будет иметь заголовок Actions - Movie Clip (Действия - Клип).
Аналогично сценарию кнопки вы не можете просто ввести набор команд. Команды должны быть помешены в программы-обработчики, реагирующие на события клипов. Однако, в отличие от кнопок, клипы реагируют на совершенно другой набор событий. В следующих разделах мы рассмотрим примеры сценариев кадра, сценариев для кнопок, а также сценариев клипов.
Что такое код ActionScript и где его размещать
ActionScript - это язык программирования, используемый программой Flash MX. По сравнению с главной временной шкалой, позволяющей создавать лишь линейную анимацию, ActionScript расширяет возможности программирования. При помощи ActionScript ваш ролик будет реагировать, например, на выбор, делаемый пользователем, или на другие события. ActionScript позволяет управлять элементами, которые видит пользователь, и вместо простой анимации показывать нелинейные презентации, интерактивные приложения или игры.
ActionScript, используемый Flash MX, был создан на основе двух источников. Первый - это набор макрокоманд, взятый из предыдущих версий Flash, в основном Flash 4, который содержал схожий, но очень простой язык программирования. Другим источником оказался JavaScript - язык, использующийся для создания небольших программ для HTML-страниц в Internet Explorer и Netscape. Новый язык стал популярен среди разработчиков Web-странии, которые являются основными пользователями Flash MX. Для того чтобы упростить изучение ActionScript, многие новые команды и синтаксис были приведены к виду, напоминающему JavaScript.
Программы ActionScript представляют собой списки инструкций, котoрые выполняются программой Flash и могут быть помешены в различные места Flash-ролика. Если вы знаете, куда поместить сценарий, это уже полдела. Давайте рассмотрим несколько мест, куда может быть помещен сценарий, а также в каких случаях он будет использован программой.
Условные выражения
Из урока 5 "Создание кнопок для пользователя" вы узнали, как пользователь может использовать кнопки для перехода от одного кадра к другому. Пользователь решает, какую часть ролика он хочет увидеть следующей, щелкает по кнопке, и сценарий, приписанный данной кнопке, отправляет ролик в соответствующий кадр.
ActionScript также может принимать решения. Эти решения основываются на сравнении значений, которое осуществляется при помощи оператора if. Например, могут сравниваться два значения. Если они равны, программа отреагирует на это определенным образом.
Приведем пример программы, которая сравнивает переменную со значением. Если значение удовлетворяет условию, код внутри фигурных скобок выполняется. В противном случае программа пропускает его.
if (a == 7) {
GotoAndPlay("special frame");
}
Символ == используется для установления тождественности двух значений. Если значения равны, условие верно. Если нет, условие ложно. Задача оператора if состоит в проверке верности условия. Если это условие верно, код в фигурных скобках выполняется.
Вы можете продлить выражение if и задать, что при невыполнении данного условия должно совершаться определенное действие. Используя оператор else после оператора if, вы можете включить еше один набор фигурных скобок, в которых будет задано какое-либо действие при невыполнении условия:
if (a =- 7) {
gocoAndPlay("special frame");
} else {
gotoAndPlay("another frame");
}
Выражение if может быть длинным и включать несколько проверок условий. Выполняется код, следующий за первым верным условием. Если ни одно условие не является верным, выполняется код, следующий за оператором else.
if (a == 7) {
gotoAndPlay ("special frame");
} else if (a == 12) {
gotoAndPlay("very special frame");
} else if (a == 15) {
gotoAndPlay(" extremely special frame");
} else {
gotoAndPlay("a not so special frame");
}
Символ == может также использоваться для сравнения двух строк. Например, для того чтобы определить, содержит ли переменная username строку "Gary", вы можете использовать следующий код:
if (username == "Gary") {
Кроме символа ==, определить, будет ли одно число соответственно меньше или больше другого, помогут символы < и >, а символы = указывают, будет ли число меньше или равно или больше или равно другому числу. Данные символы могут использоваться и при сравнении строк, в этом случае они производят сравнение исходя из алфавитного порядка.
У вас есть возможность одновременно выполнять несколько сравнений. Например, вы можете проверить, равно ли значение а определенному числу, a username определенной строке:
if ((а == 7) and (username == "Gary")) {
Предыдущая строка верна только при выполнении обоих условий. Выполнение одного из условий можно проверить при помощи оператора or:
if ((a == 7) or (username == "Gary")) {
Выражения if являются основными элементами всех программ. Они могут использоваться для изменения переменных, перехода к другим кадрам, а также для того, чтобы определить выигрыш или проигрыш игрока. Другим важным элементом программы являются ииклы, которые рассматриваются в следующем разделе.
Циклы
Условные выражения являются необходимым элементом программирования; не менее важный элемент - циклы.
Компьютеры превосходно выполняют повторяющиеся задания. Во Flash этими заданиями являются циклы. Наиболее распространенная их разновидность - цикл for. Он позволяет выполнять задание определенное количество раз. Приведем пример цикла for:
for(i=0;i
Традиционным для программирования является использование переменной i в качестве счетчика циклов программы. В данном случае i обозначает increment (приращение). Это неплохая идея - всегда давать переменной имя, обозначающее выполняемую ей функцию. В циклах for, как правило, используется именно переменная i.
На первый взгляд цикл for кажется довольно сложным. Он состоит из трех частей, разделенных точкой с запятой. Первая часть позволяет задавать определенное значение переменной. В данном случае переменной i присвоено значение 0.
Вторая часть синтаксической структуры for проверяет выполнение условия, аналогично тому, как это делалось в конструкции if. В нашем случае условие ложно, если i меньше 10.
Третья часть синтаксиса for показывает, как должна изменяться переменная в каждом новом цикле. В данном случае i каждый раз увеличивается на 1. Результатом является следующий цикл: в начале переменная i имеет значение 0, в каждом цикле это значение увеличивается на 1, цикл заканчивается, когда переменная достигает значения 10. Таким образом, значение переменной i изменяется с 0 до 9 за 10 шагов. Если запустить вышеописанный код, вы увидите в окне Output цифры от 0 до 9.
Циклы for применяются для обработки данных внутри программ, а не для анимации объектов на экране. Пока выполняется никл, на экране ничего не происходит. Короткие циклы, наподобие предыдущего примера, выполняются настолько быстро, что не оказывают никакого влияния на ролик. Однако длинные циклы могут задерживать воспроизведение ролика на несколько секунд и больше.
Приведем более распространенный пример цикла for. Предположим, у вас есть 10 клипов с именами "fox1" - "fox10", и вы хотите передвинуть их на 1 пиксел влево. Это действие будет выполнено при помощи следующего цикла:
for(i=0;i _root["fox"+i]._x++;
}
Цикл меняет значение переменной i от 1 до 10. В нем применяется объект _root, с которым вы познакомились в уроке 7 "Возможность контроля клипов пользователем". Вы можете обратиться к любому клипу главной временной шкалы при помощи объекта _root [ ] с именем клипа внутри скобок. В данном случае код представляет собой строку, состоящую из слова "fox" и числа i.
Есть еще два способа создания циклов в ActionScript. Первый - это цикл while. В отличие от счетчика приращения (например, i), цикл while продолжает выполняться до тех пор, пока условие в начале выражения while верно. В цикле do, наоборот, условие находится в конце цикла. Разница в том, что если применяется вариант while, цикл может ни разу не выполниться, а в случае do он всегда выполняется один раз. Начинающие программисты на ActionScript нечасто используют подобные циклы, однако их необходимо знать.
Создание функций
Функция - это часть кода, которая может быть использована многократно. Вы можете передавать в нее несколько значений и получать из нее новые. Примером является функция, выдающая сумму двух чисел. Вот как она будет выглядеть в ActionScript:
function sum(a, b) {
с = a + b;
return c;
}
Обычно функции помешаются в сценарии кадра главной временной шкалы. Функция задается при помощи ключевого (зарезервированного) слова function. Затем указывается имя функции, за которым следуют круглые скобки и открытая фигурная скобка {. Круглые скобки могут быть пустыми или содержать список переменных, задаваемых при вызове функции. Эти переменные называются параметрами функции (или аргументами). Например, предыдущая функция может быть вызвана следующим образом:
trace (sum (7, 12));
Результатом обращения к функции будет число 19, помещаемое командой trace в окно Output. При обращении к функции sum значение 7 передается в функцию как переменная а, а значение 12 - как переменная b. После выполнения функции команда return посылает значение , с обратно к sum. Таким образом, для выполнения своей функции команда trace использует результат sum (7, 12) - число 19.
Функции используются по двум причинам. Первая - это возможность разделить программу на более мелкие части. Программу, состоящую из 30 строк и выполняющую три различные задачи, можно заменить на три функции, состоящие из 10 строк, каждая из которых выполняет свою задачу. Это значительно облегчает работу с кодом.
Другой причиной является возможность их повторного и неограниченного использования. Таким образом, если определенная часть кода используется несколько раз, вы можете поместить ее в функцию, которую затем будете постоянно вызывать, изменяя ее входные параметры.
Исходный файл: Framelabeler.fla
Приведем пример функции, использующей в качестве входного параметра имя метки кадра. Она выполняет две задачи. Во-первых, помещает имя в текстовую переменную textFrameLabel. Это текстовое окно видно пользователю при воспроизведении ролика, оно информирует пользователя о том, в каком кадре он находится в данный момент. Второй задачей функции является выполнение команды gotoAndstop - переход к определенному кадру и остановка воспроизведения.
function gotoFrame(frameLabel) {
franeLabelText - frameLabel;
gotoAndStop (frameLabel) ;
}
Функция помешается в первый кадр главной временной шкалы вместе с командой, задающей переход ролика к начальному кадру. Так как ролик уже находится в первом кадре, команда gotoAndstop просто останавливает ролик.
gotoFrame ("introduction") ;
В примере Framelabeler.fla функция содержится в первом ключевом кадре. К каждому из пяти кадров пользователь может перейти при помощи кнопок, расположенных в нижней части экрана. Вместо команды gotoAndStop все кнопки обращаются к команде gotoFrame. На рис. 2.12 показан пример ролика. В верхнем левом углу рабочего поля находится область динамического текста. Временно он содержит слова "frame label". При первом обращении к функции gotoFrame они будут заменены на "introduction".

Рисунок 2.12 Ролик состоит из пяти кадров и пяти кнопок для перехода к каждому кадру. Текстовое окно отображает имя текущей метки кадра
Преимущество использования одной функции для контроля всей навигации заключается не только в меньшем количестве нажатий на клавиши при программировании. Предположим, что к моменту завершения программы вы 100 раз обратились к функции gotoFrame. Затем вы решили удалить окно textFrameLabel или немного изменить его. Если бы вы не использовали функцию, то вам пришлось бы удалять или изменять код в 100 местах. Но так как все ваши навигационные кнопки используют функцию gotoFrame, то для изменения их поведения достаточно изменить только ее.
Массивы
Никакое введение в язык программирования не было бы полным без рассмотрения массивов. Хотя множество простых операций может быть выполнено без применения массивов, человек, не умеющий работать с массивами, не может считаться настоящим программистом.
Массив является разновидностью переменной. Переменные, которые вы использовали до сих пор, могут содержать одно значение: число или строку. Массив может содержать ни одного, одно и больше значений. Вот как выглядит массив:
myArray - ["Apple", "Orange", "Peach", "Plum"];
Для обращения к элементу массива используется специальный синтаксис:
myItem. = myArray [1];
Переменная myItem будет иметь значение "Orange", так как отсчет положений в массивах, так же как и в строках, начинается с 0.
Несложно догадаться, что массивы применяются для хранения множества однотипных данных. Для выполнения операций над массивами предназначено несколько функций. Прежде всего, давайте рассмотрим, как создаются массивы. Это можно сделать несколькими способами. До сих пор мы рассматривали только способ, при котором все элементы массива задаются сразу. Вы также можете создать пустой массив и добавлять в него элементы:
myArray = new Array();
myArray.push("Apple");
myArray.push{"Orange");
myArray.push("Peach");
myArray.push("Plum");
Первая строка данного кода создает пустой массив. Каждая из следующих четырех строк добавляет в массив один элемент при помоши команды push. По сравнению со способом "все сразу" данный способ кажется более сложным, однако он незаменим при построении массивов, все элементы которого не известны заранее. Например, вы можете позволить пользователю ввести данные, а затем добавить их в массив.
Длину массива можно узнать так же, как и длину строки:
myLength = myArray.length;
Вы уже знаете, как получить доступ к отдельному элементу массива при помоши квадратных скобок. Используя команду pop, вы сможете взять из массива значение последнего размешенного там элемента. При этом из массива он удаляется. В нашем примере мы передаем его в окно Output. Следующий сегмент кода добавляет в массив четыре элемента, а затем, используя цикл while, удаляет конечные элементы массива и перемешает их в окно Output:
myArray = new Array();
myArray.push("Apple");
myArray.push("Orange");
myArray.push("Peach");
myArray.push("Plum"); while (myArray.length>0) ( trace (myArray.pop());
Первой строкой в окне Output является "Plum", последней- "Apple", так как команда pop берет элементы в порядке, обратном помещению элементов массива {стековая схема: "последний вошел, первый вышел" -First In Last Out).
Массивы можно упорядочить. В случае, если элементами массива являются числа, Flash упорядочит их в цифровой последовательности. Если это строки, они будут упорядочены по алфавиту:
myArray = new Array ();
myArray.push("Peach"};
myArray.push("Orange");
myArray.push{"Apple");
myArray.push("Plum"};
myArray.sort{);
trace(myArray.toString());
Обратите внимание на последнюю строку кода, которая содержит функцию tostring для приведения массива к виду, пригодному для отображения в окне Output, то есть преобразует все элементы массива в строку. При помоши данной функции вы можете убедиться в том, что массив соответствует вашим требованиям. Наконец, функция splice позволяет удалять один или несколько элементов из массива:
myArray = [ "Apple", "Orange", "Peach" "Plurr." ] ;
myArray.splice(2,1);
Команда splice может выполнять несколько функций. В данном примере она содержит два параметра. Первый задает позицию, с которой начинается удаление элементов (считая от 0!), второй - количество удаляемых элементов. В нашем случае будет удален элемент "Peach", находящийся в позиции 2. Изменив второй параметр на 2, вы удалите и " Peach" и "Plum". Убрав второй параметр, вы удалите все элементы массива.
Функция splice используется также для добавления элементов. Добавляемый элемент задается третьим параметром:
myArray = [ "Apple", "Orange", "Peach" "Plurr." ] ;
myArray.splice(2,1, "Pear");
В данном примере удаляется элемент м Peach", а его место занимает элемент " Fear". Четвертый и последующие параметры используются для добавления второго и более элементов. В случае, если значение второго параметра окажется равно 0. никакие элементы удалены не будут. Теперь, когда у вас есть представление об основах ActionScript, самое время применить эти знания для создания вполне профессиональных фрагментов Flash-роликов. В следующей главе мы создадим несколько подобных фрагментов, и затем, начиная с главы 5 "Создание визуальных эффектов", приступим к написанию целых программ.
Ваша первая программа на ActionScript
Исходный файл: Helloworld.fla
Первая команда, которую вы изучите, - trace, которая предназначена для передачи информации в окно Flash Output. Окно Output представляет собой небольшое текстовое окно, выводимое на экран во время предварительного просмотра ролика во Flash. Обычно оно используется для вывода отладочных сообщений при разработке программы.
Хотя в действительности данная команда не будет применяться в законченном Flash-ролике, приводимый здесь пример наглядно демонстрирует, что при помощи ActionScript вы можете заставить Flash выполнить указанные вами действия.
Для начала создайте новый Flash-ролик. При этом автоматически создается временная шкала с одним слоем и одним ключевым кадром. Выделив его и нажав F9, вызовите окно Actions. Затем при помощи всплывающего меню в правом верхнем углу окна переключите его в экспертный режим.
Теперь вы сможете поместить курсор в пустое программное поле в правой части окна Actions. Введите следующую строку:
trace ("Hello World!");
Точка с запятой ставится в конце каждой команды, как в примере с trace.
Команда trace - это встроенная функция Flash. В круглых скобках указываются параметры функции. Параметры - это входные данные, необходимые функциям для выполнения их задачи. Команда trace использует один параметр: строку, которая помешается в окно Output. Некоторые функции содержат один параметр и более, в то время как другие - ни одного.
Ваш экран должен выглядеть примерно так, как изображено на рис. 2.3. Здесь вы видите один слой и один кадр на временной шкале. Окно Actions имеет заголовок Actions - Frame. Это обозначает, что содержащийся в окне код ActionScript относится к выбранному в данный момент ключевому кадру. Единственным элементом программного листинга является команда trace. Попробуйте самостоятельно создать данный ролик.

Рисунок 2.2 Программа "Hello World" описывает первый и единственный кадр
Для того чтобы запустить программу, выберите команду Control -> Test Movie (Контроль -> Запустить пробное воспроизведение ролика). В течение секунды Flash создаст swf-файл и откроет его в окне предварительного просмотра. Окно останется пустым, так как в ролике нет никакой графики. Затем будет открыто окно Output со словами "Hello World!" (рис. 2.4). Это был важный шаг в изучении ActionScript. Мы дали Flash команду. В ответ Flash показал, что он понимает ее и слушается вас.

Рисунок 2.3 В окне Output содержится результат выполнения команды trace
Программа "Hello World" появилась вместе с первыми языками программирования и стала традиционной. Это самая элементарная программа, которая обычно приводится как первый пример при обучении любому языку программирования, будь то ассемблер громадной ЭВМ, Basic, Pascal, С, Java или ActionScript. Только что вы прошли по следам миллионов программистов, начинающих изучать свое ремесло.
Контроль воспроизведения ролика
В уроке 2 "Использование окна Actions" мы бегло ознакомились с командой ActionScript gotoAndPlay. Эта команда приказывает Flash не принимать во внимание следующий кадр временной шкалы, а вместо этого перейти к совершенно другому кадру. При помощи команды gotoAndPlay вы можете контролировать воспроизведение Flash-ролика.
Создайте новый Flash-ролик. В этот раз он будет содержать несколько кадров. Создайте последовательность из четырех ключевых кадров и присвойте им имена начиная с "parti" и заканчивая "part4". Эти кадры представляют собой четыре части анимации. Кроме этого, в каждый из четырех кадров следует поместить статический текст, сообщающий пользователю о том, какую часть он в данный момент видит на экране.
В примере Gotoandplay.fla в каждый из четырех ключевых кадров был помешен статический текст "PART 1"- "PART 4". Текст "PART 1" появится в ключевом кадре "part1", текст "PART 2" - в ключевом кадре "part2" и т.д.
Ключевые кадры разделены несколькими кадрами, чтобы были видны названия меток на главной временной шкале. На рис. 2.5 показана главная временная шкала, содержащая четыре метки. Выбран второй ключевой кадр, поэтому на рабочем поле отображен текст "PART 2".
Выделив второй ключевой кадр, откройте окно Actions. Затем введите в окне следующую команду:
gotoAndPlay ("part4");
Обратите внимание, что после добавления в ключевой кадр кода Action-Script на временной шкале в соответствующем кадре появляется строчная буква "а".

Рисунок 2.5 Ролик содержит четыре ключевых кадра и сценарий, помешенный во второй ключевой кадр. Выбран второй ключевой кадр, и в окне Actions отображается соответствующий сценарий
Это единственный код ActionScript в ролике. При воспроизведении ролик начинается с ключевого кадра "part 1" и на экране появится текст "PART 1". Затем ролик будет двигаться по временной шкале до ключевого кадра "part2", где находится код ActionScript. По команде Flash перейдет к ключевому кадру "part4'. При этом текст "PART 2" не успеет появиться на экране1. Ролик будет находиться в кадре "part4", на экране окажется текст "PART 4".
Ролик продолжит движение по временной шкале до конца. Затем возвратится к первому кадру и опять покажет текст "PART 1". Этот цикл повторяется бесконечно.
При помощи ActionScript вы заставили Flash отступить от последовательного воспроизведения анимации. Ролик должен был последовательно проигрываться с кадра "part 1" к "part2", затем к "part3" и к "part4" однако по вашему сценарию он пропустил сразу два кадра - "part 2" и "part З'. С ActionScript вы получаете возможность контролировать порядок воспроизведения кадров Flash-ролика.
Точнее говоря, если в кадре имеется сценарий, программа сначала исполняет сценарий, а потом прорисовывает кадр.
Давайте рассмотрим другой пример. По той же схеме создайте небольшие ключевые кадры в конце каждой части ролика. Мы будем создавать сценарии, воспроизводимые не в начале каждой части, а в ее конце.
Исходный файл: Nonlinear.fla
На рис. 2.6 показано устройство ролика, включающего четыре маркированных ключевых кадра, как и в предыдущем примере, а также четыре ключевых кадра в конце каждой части ролика. В этих немаркированных кадрах содержится код.

Рисунок 2.6 Ролик состоит из четырех частей. Каждая часть начинается с маркированного ключевого кадра и заканчивается немаркированным ключевым кадром, содержащим небольшой сценарий
Ключевой кадр, следующий за "part1", содержит код:
gotoAndPlay ("part3");
Ключевой кадр, следующий за "part2", содержит код:
gotoAndPlay ("part4");
Ключевой кадр, следующий за "рагtЗ", содержит код:
gotoAndPlay ("part2");
Ключевой кадр, следующий за "part4"', содержит код:
gotoAndPlay ("part1");
При запуске ролика из файла Nonlinear.fla на экране появляется надпись "PART 1". Затем ActionScript задает переход ролика не к кадру "part2", а к "part3". Таким образом, ролик переходит от надписи "PART 1"к "PART 3". Затем, после кадра "'part3", ролик возвращается к "part2", а после него к "part4". Весь ролик воспроизводится в таком порядке - "PART 1", "PART 3", "PART 2" и "PART 4". Эта последовательность затем повторяется.
При помощи ActionScript вы полностью заменили обычную анимационную последовательность на свою собственную.
Приведенные выше примеры дают предсказуемый результат, однако у вас есть возможность использовать команду gotoAndPlay по-другому, например в сочетании с кнопками, чтобы предоставить пользователю контроль над порядком воспроизведения ролика.
Создание кнопок для пользователя
Исходный файл: Stop.fla
В предыдущем примере мы рассмотрели возможность управления роликом при помощи ActionScript без всякого вмешательства пользователя. Давайте добавим несколько кнопок, щелкнув по которым, пользователь сможет запустить воспроизведение той или иной части ролика.
Предоставить пользователю больше контроля над воспроизведением ролика можно, прежде всего лишив этого контроля Flash. Flash начинает воспроизведение анимации с первого кадра, затем переходит к следующему и т.д. При помощи команды stop () вы можете остановить воспроизведение анимации на первом кадре.
На рис. 2.7 изображен ролик из файла Stop.fla. Он состоит из четырех кадров, каждому из которых соответствует метка на временной шкале и текст на рабочем поле. В первый кадр включен небольшой сценарий с командой stop(). Воспроизведение ролика начинается и заканчивается в кадре 1.
Теперь мы можем предоставить немного самостоятельности пользователю. Создайте простой эталон кнопки и поместите его на рабочий стол. Не следует выдумывать ничего необычного. В примере кнопка представляет собой маленький кружок.
Следующим вашим шагом будет создание нового слоя с одним кадром. Теперь в ролике будут участвовать одни и те же элементы. В данный слой мы поместили четыре различных копии одной и той же кнопки из библиотеки. Результат изображен на рис. 2.8.

Рисунок 2.7 Данный ролик состоит из последовательности нескольких кадров, однако команда stор() останавливает его воспроизведение на первом кадре

Рисунок 2.8 Данный ролик состоит из двух слоев. Первый слой разделен на четыре части, которые содержатся в четырех кадрах, второй включает один ключевой кадр.
В первом кадре данного ролика будет использоваться та же самая команда stop(), которая остановит воспроизведение ролика сразу после его начала. В нижней части экрана размешены четыре кнопки. Каждой из них будет приписан отдельный сценарий. Первый сценарий изображен на рис. 2.8. Первая кнопка выбрана,и в окне ActionScript отображается ее сценарий:
on (press){
gotoAndStop("part1");
}
Так выглядит обычный сценарий кнопки. Поведение кнопки во время выполнения различных действий с ней задается программами-обработчиками. В нашем случае это действие press. Синтаксический элемент on обозначает начало программы-обработчика. В фигурные скобки заключаются команды реакции на события.
В нашем примере используется команда gotoAndStop - разновидность команды gotoAndPlay. В отличие от первой команды, задающей переход к новому кадру и остановку воспроизведения ролика, вторая команда переходит к другому кадру и запускает его воспроизведение.
Помимо этого сценария, три подобных приписаны трем другим кнопкам. Единственным их отличием является то, что они задают переход к кадрам "part 2", "part 3" и "part 4".
Исходный файл: Navigation.fla
При запуске данного файла начинается воспроизведение ролика, остановленного в первом кадре. Теперь пользователь может щелкнуть по одной из четырех кнопок для перехода к одному из четырех оставшихся кадров. Попробуйте запустить ролик.
Это ваш первый настоящий Flash-ролик. Вместо простого текста "PART 1" - "PART 4", показываемого в каждом ключевом кадре, вы можете поместить презентацию наподобие той, которая создается в PowerPoint или других программах. Здесь демонстрируются возможности Flash, выходящие за рамки простой анимации.
Анимация при помощи ActionScript.
Исходный файл: Animate.fla
Теперь научимся перемешать предметы по рабочему полю при помощи ActionScript. Необходимо будет назначить клипу сценарий подобно тому, как мы сделали это для кнопки на нашем предыдущем занятии.
Сначала создайте новый ролик. Затем поместите клип на рабочее поле. В примере Animate.fla на рабочее поле было помешено изображение лисы. Если хотите, нарисуйте что-нибудь более простое, например круг.
Когда употребляется термин "ролик" (movie), речь идет обо всем файле проекта. Термин "клип" употребляется для символа типа movie clip.
Вы можете поместить на рабочее поле экземпляр любого клипа, имеющегося в библиотеке. На данный момент наш фильм состоит из одного слоя и одного кадра, помешенного на рабочее поле (рис 2.9).

Рисунок 2.9 Ролик содержит клип и назначенный ему сценарий
Сценарий, назначенный клипу, использует программу-обработчик подобно сценарию кнопки в предыдущем занятии. Чтобы задать программу обработки, вместо командной строки on введите строку onCIipEvent, которая определяет события для клипов ролика. В данном случае событие будет следующим: enterFrame. Это автоматическое событие, происходящее при каждом обращении к данному кадру. Если ролик должен воспроизводиться со скоростью 12 кадр/с, оно должно посылаться в программу обработки 12 раз в секунду.
Если ролик остановлен командой stop () или просто состоит из одного кадра, то кадр "зацикливается", то есть перерисовывается с той скоростью, которая задана ролику
Подобно программе on (press) в сценарии кнопки, команды реакции на событие onClipEvent (enterFrame) заключаются в фигурные скобки. В данной программе будет только одна команда, перемещающая клип на один пиксель влево. Давайте взглянем на сценарий и проанализируем, какие действия в нем выполняются.
OnClipEvent(enterFrame) {
this._ x -- ;
}
Команда this._х --, вероятно, будет совершенно непонятной для людей, не знакомых с языками программирования, поэтому разберем ее по частям.
Команда this обозначает обращение команды к объекту, который ее содержит. В данном случае this используется для обращения к клипу, которому назначен этот сценарий.
За командой this следует точка, обозначающая обращение к свойству объекта. В нашем примере _х относится к горизонтальному положению клипа.Итак, this._x определяет горизонтальное положение клипа. Символ -- является декрементом (командой уменьшения значения). Он уменьшает значение стоящей перед ней величины на 1 (пункт). Таким образом, команда this._x -- берет значение горизонтального положение клипа и вычитает 1, благодаря чему клип перемещается влево.
Если клип необходимо переместить вправо, используется команда ++, которая называется инкрементом (это команда увеличения значения). Если вы хотите переместить клип вправо или влево сразу на несколько пикселов, используйте соответственно += или -=:
OnClipEvent(enterFrame) {
this._x -= 5;
}
Данная команда переместит клип сразу на пять пикселов.
Возможность управления клипами пользователем
Исходный файл: Usercontrol.fla
А теперь давайте сделаем так, чтобы клип двигался вслед за курсором.
В предыдущем занятии мы узнали, как получить доступ к горизонтальной позиции клипа. При помоши параметра _у так же легко оперировать изменением координаты по вертикали. Теперь все, что нам нужно, - это привязать данные координаты к курсору.
Местоположение курсора определяется двумя параметрами: _xmouse и _ymouse, которые представляют собой координаты курсора по вертикали и горизонтали. Возникает следующий вопрос: чьи это параметры?
Это могут быть параметры любого клипа или самого ролика. Например, команда this ._xmouse определяет горизонтальное положение мыши по отношению к центру текущего клипа.
Нам нужно установить положение клипа по отношению к рабочему полю. Для того чтобы получить параметры рабочего поля, вместо идентификатора this следует использовать _root. Так, переменная _root ._xmouse определяет горизонтальное расположение мыши относительно левого верхнего угла рабочего поля.
Для того чтобы привязать координаты клипа к координатам курсора, необходимо изменить параметры _х и _у клипа в соответствии с параметрами _xmouse и _ymouse рабочего поля. Вот как будет выглядеть программа:
On.ClipEvent (enterFrame) {
this._x = _root._xmouse; this._y = _root._ymouse;
}
На рис. 2.10 показан "собранный" ролик Usercontrol.fla. Он состоит из одного кадра со скриптом, содержащим команду stop(). Клипу назначен вышеописанный сценарий. Это все, что требуется. При воспроизведении ролика клип с лисой будет следовать за курсором.

Рисунок 2.10 По сценарию данный клип перемещается вcлед за курсором
Теперь, когда вы умеете управлять воспроизведением ролика и перемещением клипа, давайте рассмотрим основные элементы программирования в ActionScript.
Использование переменных
Переменные представляют собой поименованные области памяти, содержащие какую-либо информацию, такую как числа или последовательность символов. Например, вы можете создать переменную и поместить в нее число 5. Если вы прибавите к данной переменной число 2, она будет содержать число 7. Вот как эти действия будут выглядеть в ActionScript:
myVariable = 5;
myVariable += 2;
myVariable - это имя созданной вами переменной. Для того чтобы создать переменную во Flash, необходимо просто один раз упомянуть ее в тексте программы. Flash автоматически создает переменную с соответствующим именем (в ActionScript не требуется какой-либо специальной инициализации переменных). В нашем примере была создана переменная myVariable со значением 5. В следующей строке к данной переменной прибавляется значение 2. Теперь переменная myVariable содержит число 7.
Очень важно присвоить переменной содержательное имя. Оно должно отражать выполняемую ей задачу. Например, если переменная предназначена для хранения имени пользователя, ее лучше назвать, допустим, "userName". Позднее, просматривая код, вы сразу поймете, для чего используется данная переменная.
В переменную можно также помещать строки. Строка - это последовательность символов наподобие “Hello World”. Так же как и число, строку можно сохранить в переменной при помощи символа =.
myVariable = "Hello World";
Переменные во Flash не делятся на типы. Классификация переменных -это ограничение типа данных, хранимых в данной переменной, которое применяется в других языках программирования. Это означает, что если переменная предназначена для хранения чисел, она может использоваться только для хранения чисел, но не для хранения строк. В ActionScript нет такого ограничения, поэтому любая переменная может хранить любые объекты, например числа или строки.
Помимо чисел и строк переменные могут содержать другие элементы, например указатель клипа. Вспомните, как в двух предыдущих уроках использовался элемент this для ссылки на текущий клип. Вы можете присвоить значение this переменной и с ее помощью ссылаться на клип.
Использование подобных элементов помогает управлять роликами, где содержится более чем один клип.
Вы будете часто сталкиваться с подобными ситуациями в играх, рассматриваемых в этой книге. На данный же момент вам достаточно знать, что переменные могут содержать числа, строки и ссылки на клипы.
Все переменные, использованные в этом уроке и в остальной книге, это глобальные переменные. Это значит, что после того как вы их задали, к ним можно обращаться из ролика или других клипов. Также с помощью ключевого слова "var" вы можете определить локальные переменные. Локальные переменные, определенные в какой-либо функции, недоступны к использованию в остальном коде. Как локальную переменную, например, удобно определять счетчик цикла, используемого внутри функции.
Выполнение операций
Вам наверняка понадобится изменять данные, хранящиеся в переменной. Мы уже рассматривали, как с помощью команд ++ или += изменять значение переменной. В вашем распоряжении также имеется большой набор других операций.
Давайте начнем с переменных, содержащих числа. Вы можете выполнять большое количество математических операций с числами при помощи символов +, -, / и *. Приведем несколько примеров.
Допустим, у вас есть две переменные: а и Ь. Вы можете сложить их и поместить результат в переменную с.
a = 7;
b = 5;
c = a + b;
В предыдущем примере с будет в результате содержать число 12. Вот еще один подобный пример:
c = a - b;
c = a * b;
c = a / b;
Переменная с получит значение 2 в первой строке, 35 - во второй строке и 1,4 - в третьей строке.
Вы также можете выполнять более сложные математические операции при помощи специальных функций, встроенных во Flash. Все они содержатся в объекте Math, за которым следует точка и имя функции. Например, при помощи функции Math.sqrt можно вычислить квадратный корень числа:
a = 9;
b = Math.sqrt(a);
Значением b является 3 - квадратный корень из 9.
Один из важнейших элементов компьютерного языка, позволяющий программистам создавать игры, - генератор случайных чисел. Без случайных чисел игры были бы полностью предсказуемыми и скучными.
Flash генерирует случайные числа при помощи функции Math. random (). При этом генерируются случайные десятичные значения между 0.0 и 1.0. Нужные числа получают, умножая данные значения на целое число, а затем переводя их в целое число при помощи функции int. Например, следующая строка служит для генерации случайного числа от 0 до 9:
myRandomNumber = int(Math.random()*10) ;
Другие математические функции будут рассмотрены по мере их появления в примерах.
Функции могут применяться и к строкам. Например, для объединения двух строк может использоваться символ +:
а = "Hello";
Ь = "World";
с = а + b;
В итоге переменная с превратится в строку "HelloWorld". Обратите внимание на то, что между двумя этими словами нет пробела. Вам следует дать Flash команду ввести пробел. В результате следующий код создаст "HelloWorld":
а = "Hello";
b = "World";
с = а + " " -b;
Более простым способом объединения двух строк является использование синтаксических элементов * = :
а = "Hello";
b += "World";
Теперь, когда вы узнали больше о переменных и их использовании, рассмотрим, как с помощью ActionScript организовать выполнение кода по условию.
Обработчики событий
Во Flash 5 единственным способом отслеживания таких событий, как, например, enterFrame, было использование обработчиков onClipEvent в сценариях клипа. В версии MX появилась возможность использовать обработчики прямо в сценарии кадра.
Вот простой пример. Этот сценарий помещен в кадр и посылает сообщение в окно Output при каждом обращении к кадру.
root.onEnterFrame = function() {
trace("enterFrame Event");
}
Вместо команды trace вы можете использовать другие команды аналогично тому, как это делалось на протяжении этого урока. Можно также определить имя для функции, обрабатывающей событие. Тогда предыдущий пример можно записать в таком виде:
root.onEnterFrame = myFunction;
function myFunction() {
trace("enterFrame Event");
}
С помощью этого приема можно обращаться к любым событиям, например onMouseUp, onKeyUp, onLoad и т.д. Полное описание процедур обращения к событиям вы можете найти в документации. Пример использования данной технологии можно найти в главе 13 начиная с игры "Найди картинку".
Создание клипа сценария
Единственным способом управлять несколькими клипами будет поместить код в точку, контролирующую их все. Например, если у вас есть 10 клипов, вы можете поместить код в первый клип, который будет контролировать все остальные.
Почему бы вместо того, чтобы возлагать контроль на один из клипов, нам не создать клип, специально для этого предназначенный? Данный распространенный прием позволяет легко запомнить, куда вы поместили ваш код. Я назвал такой клип "actions movie clip" (клип сценария).
такой клип удобно называть контроллером.
Начните с создания при помоши инструмента Text небольшого текстового окна на рабочем поле и напишите в нем слово "actions" для того, чтобы его можно было легче идентифицировать.
Перед окончательной пубикацией ролика лучше удалить надпись "actions" из клипа сценария, так как итоговый swf-файл должен занимать как можно меньше места
Затем, выделив текстовое окно, выберите команду Insert -> Convert to Symbol для преобразования его в клип под названием "actions".
Переместите его на серую область за пределами рабочего поля, так чтобы пользователь не видел слово "actions".
Данный клип используется для назначения сценария, который будет управлять роликом. Предположим, вам необходим ролик, создающий 10 копий эталона из библиотеки и немного поворачивающий их с каждым новым циклом.
Исходный файл:
actionsMC.fla
Прежде всего создайте эталон. В диалоговом окне Symbol Linkage Properties установите флажок Export This Symbol и укажите имя "sample" (см. файл actionsMCfla).
Код, написанный ниже, будет включен в клип "actions". Он будет находиться внутри программы обработки onClipEvent и состоять из двух частей. Первый обработчик будет отзываться на событие load. Событие load происходит при первом появлении клипа. Код выполняется один раз. В данном случае следует воспользоваться возможностью и создать 10 новых клипов:
OnClipEvent (load) {
// Создаем 10 клипов,
for(i=0;i
_root.attachMovie("sample","sample"+i,i);
// Устанавливаем координаты
_root["sample"+i]._x = i*50 + 50;
_root["sample"+i]._y = 100; } }
Координаты клипов задаются одновременно с их созданием. Значение по вертикали равно 100, координата по горизонтали может иметь различные значения от 50 до 500. Результат показан на рис 3.6.

Рисунок 3.6 Эти 10 клипов были созданы из эталона при помощи ActionScrip
Вторая часть кода находится в программе обработки onClipEvent (enterFrame). Код выполняется в каждом цикле клипа "actions". Если клип воспроизводится со скоростью 12 кадров в секунду, код будет выполняться также 12 раз в секунду.
onClipEvent (enterFrame) {
// Поворачиваем каждый клип в цикле,
for(i=0;i
_root["sample"+i]._rotation += 5;
}
}
Данный код циклически выполняется во всех клипах и поворачивает каждый их них на 5 градусов. В результате на рабочем поле будет 10 вращающихся клипов.
Исходный файл:
Gears.fla
Я также создал улучшенную версию ролика под названием Gears.fla. За исключением кода ролик ничем не отличается от предыдущего. В Gears.fla клипы расположены таким образом, что зубья шестеренок соприкасаются. Чтобы создать эффект работающего механизма, каждый ролик изначально повернут относительно предыдущего на 15 градусов. Соседние зубья каждой шестеренки расположены с интервалом в 30 градусов, поэтому зубъя соседних шестеренок сцепляются. Кроме того, каждая шестеренка вращается в направлении, отличном от направления врашения предыдущей. Вот как выглядит код:
onClipEvent (load) {
initialRotation = 0;
// Создаем 10 клипов,
for(i=0;i
/7 Присоединяем очередной клип.
_root'.attachMovie ("sample","sample"+i , i) ;
// Устанавливаем координаты
_root["sample" + i]._x = i * 37 ;
_root["sample"+i]._y = 100;
// Устанавливаем каждому следующему поворот
// на 15 градусов относительно предыдущего.
_root["sample"+l]._rotation = initialRotation;
initialRotation += 15;
onClipEvent (enterFrame) {
// Пробегаем все клипы через один.
for(i=0;i
// Поворачиваем по часовой стрелке.
_root [ "sample"+i] ._rotation += 5;
// Следующий поворот против часовой стрелки.
_root["sample"*(i+1)],_rotation -= 5;
}
}
Чтобы понять, как устроен код, откройте ролик Gears.fla и поработайте с ним. Этот, а также многие другие коды, которые вы встретите в данной книге, невозможно объяснить только теоретически. Для того чтобы до конца понять устройство и работу примеров, следует поработать с ними.
Контроль воспроизведений клипа
Исходный файл: Mcplayback.fla
Клипы представляют собой как бы небольшие ролики внутри основного Flash-ролика. Они включают полноценную временную шкалу со слоями, а также большинство элементов основного ролика. И основной Flash-ролик, и клипы можно контролировать при помощи команд play() и stop().
В библиотеке файла под названием Mcplayback.fla, находится клип "myMovieClip". Этот клип состоит из 10 кадров, промаркированных для того, чтобы вы знали, какой кадр клипа воспроизводится в данный момент.
Перетащив клип из библиотеки на рабочее поле, вы создадите его копию, которой можно и даже нужно присвоить имя. Для этого используйте панель Properties (Свойства), изображенную на рис. 3.1.

Рисунок 3.1 В панели Properties можно присвоить имя копии клипа
Вы наверняка заметили, что копия клипа имеет такое же имя, как и клип в библиотеке. Обычно это делается при создании одной копии клипа. Имя копии легче запомнить, если оно совпадает с именем объекта библиотеки.
Библиотека ролика, рассматриваемого в примере, также содержит пять кнопок. Они помешены на рабочее поле под копией клипа. Присваивать имена копиям кнопок необязательно, впрочем, вы и не сможете этого сделать. В любом случае код не может ссылаться на кнопку, поэтому в имени нет необходимости.
После добавления клипа и пяти кнопок рабочее поле будет иметь при мерно такой вид, как показано на рис. 3.2. Кнопки не только выглядят, но и используются как кнопки управления видеомагнитофоном.

Рисунок 3.2 Кнопки позволяют контролировать воспроизведение клипа
Пять кнопок позволяют полностью контролировать клип. Кнопка Play (Воспроизведение) запускает воспроизведение ролика. При достижении конца клипа воспроизведение начинается снова с первого кадра. Кнопка Stop (Стоп) останавливает воспроизведение ролика в текущем кадре. Кнопка Rewind (Перемотать) возвращает клип к первому кадру. Кнопки Previous (Предыдущий) и Next (Следующий) продвигают клип на один шаг соответственно назад или вперед.
Прежде чем передать контроль над клипом пользователю, необходимо остановить клип. Обычно клипы запускаются сразу же после своего появления на рабочем поле. Чтобы предотвратить это, в первый кадр главной временной шкалы был помещен следующий сценарий, останавливающий анимацию клипа, а также сам ролик:
myMovieClip.stop();
stop () ;
Точка в первой строке сценария показывает, что функция stop () будет выполнена для копии клипа "myMovieClip". Вторая строка не содержит имени копии, поэтому команда выполняется в месте расположения сценария - в данном случае в главной временной шкале.
В сценариях для кнопок команды клипу посылаются также при помоши точки. Вот сценарий кнопки Play, задающий воспроизведение клипа:
on (press) {
myMovieClip.play() ;}
Кнопка Stop посылает клипу команду stop () :
on (press) {
nyMovieClip.stop() ;}
Кнопка Rewind задает переход клипа к первому кадру и его остановку. Это действие выполняет команда gotoAndstop() с параметром 1.
on (press) {
myMovieClip.gotoAndStop(); }
Кнопки Previous и Next перемешают клип на один кадр вперед или назад. Эти действия выполняются при помоши команд prevFrame () И nextFrame():
on (press) {
myMovieClip.prevFrame () ;}
on (press) {myMovieClip.nextFrame ();}
Хотя целью данного урока было научить вас управлять воспроизведением клипов, вы можете использовать данный пример как руководство для воспроизведения анимации и даже слайд-шоу во Flash.
Применение метода "Перетащи и положи" к клипам
Исходный файл: Dragsimple.fla
Важным свойством интерфейса, будь то игра или приложение, являете возможность перетаскивать элементы по экрану. Во Flash это можно сде лать несколькими способами. Мы рассмотрим три из них.
Команда startDrag задает автоматическое следование клипа за курсором. Пример Dragsimple.fla демонстрирует самый простой способ применения данной команды.
Клип под названием "circle" с изображением круга был помешен на рабочее поле. Как только ролик запускается, нижеприведенная команда задает его движение следом за курсором. Она также задает остановку анимации главной временной шкалы, чтобы ролик не продолжал воспроизведение следующих кадров.
startDrag("circle", true);
stop () ;
В нашем примере команда startDrag использует два параметра. Первый - это имя перетаскиваемого клипа. Второй - ключевое слово true которое в данном случае задает привязку центра объекта к курсору. Ее второй параметр имеет значение false, за основу будет взято расстояние между курсором и центром клипа на момент выполнения командь startDrag. Ключевые слова true и false называются булевыми константами.
Они могут использоваться в случае, если атрибут либо действует, либо нет, а также отображать результат сравнения, например "а = = b.
В примере Dragsimple.fla клип "circle" следует за курсором. Однако чаше всего применяется другой способ перетаскивания: пользователь подводит курсор к объекту, нажимает кнопку мыши, перетаскивает объект в нужное место и отпускает кнопку.
Исходный файл: Dragcomplex.fla
Подобную манипуляцию можно осуществить с клипом, внутри которого содержится кнопка. В файле Dragcomplex.fla в тот же самый клип "circle" была помешена невидимая кнопка (в ней заполнен лишь один кадр "Hit"). Таким образом, клип circle включает такую же графику, как и в примере Dragsimple.fla, и, помимо этого, кнопку. Кнопке назначен следующий сценарий: когда пользователь нажимает кнопку, выполняется команда startDrag, когда отпускает - команда stopDrag.
on (press) {
startDrag("",false) ;
on (release) {
stopDrag();
}
Пустые кавычки внутри команды startDrag сообщают Flash, что перетаскиваться будет текущий клип. Кнопка находится внутри клипа "circle", поэтому перемещаться будет именно он. false в качестве второго параметра означает, что клип не будет привязан к центру курсора, а сохранит первоначальное расстояние между курсором и центром клипа. При этом будет создаваться впечатление, что курсор схватил круг в некоторой точке и перетаскивает его за нее.
Команда stopDrag не требует никаких параметров. Одновременно может перетаскиваться только один клип, поэтому команде необходимо лишь остановить текущее действие перемещения, благодаря чему клип вернется в неподвижное состояние.
Одним из недостатков команды startDrag является то, что одновременно может быть перемешен только один клип. Кроме того, клип перемешается автоматически, поэтому за его движением трудно проследить. По этой причине вам не помешает знать еше один способ перетаскивания клипа.
Исходный файл: Dragbetter.fla
Соответствующий код содержится в файле Dragbetter.fla. Ролик устроен аналогично ролику из примера Dragcomplex.fla, клип которого содержит невидимую кнопку. Однако данной кнопке назначен совершенно другой сценарий. Согласно данному сценарию, переменная drag получает значение true, когда пользователь нажимает на кнопку, и значение false, когда отпускает.
on (press) {
drag = true;
on (release) {
drag = false;
}
Переменная drag является глобальной переменной и совместно используется всем кодом клипа. В зависимости от значения drag сценарий определяет, должен ли клип следовать за курсором.
Сценарий устанавливает соответствие между переменными _х, _у перетаскиваемого клипа и _xmouse, _ymouse ролика. Два последних параметра описывают положение курсора мыши относительно рабочего поля основного ролика.
onClipEvent (enterFrame) {
if (drag) {
this._x = _root._xmouse;
this._y = _root._ymouse;
}
}
Ключевое слово this обозначает ссылку на текущий объект. Сценарий назначен клипу "circle", поэтому this относится к нему. В следующем разделе мы рассмотрим другие способы обращения к клипам на различных уровнях.
Клипы и уровни
Начинающему программисту на ActionScript будет трудно понять, каким образом устроены клипы и уровни. Клип можно представить как ролик внутри основного Flash-ролика. Этот клип имеет свои переменные и атрибуты, отличные от параметров и атрибутов основного ролика.
Каждый раз, когда вы помешаете клип на рабочее поле, вы создаете новый объект. Основной Flash-ролик является объектом, а клип - объектом внутри этого объекта.
Flash-ролик можно сравнить с коробкой, полной игрушек. Если вы раскрасите коробку в синий цвет, игрушки не станут синими. Каждая из них сохранит свой первоначальный цвет. С другой стороны, если вы перенесете коробку на другое место, остальные игрушки последуют за ней, сохранив при этом свои свойства, такие как цвет и положение внутри коробки.
Предположим, коробка с игрушками закрыта, и вы просите кого-то в комнате достать машинку. Если человек не знает, что игрушка находится внутри коробки, ему будет нелегко это сделать. Недостаточно просто сказать: "Достань машинку". Необходимо сказать: "Достань машинку, которая находится в коробке".
Подобным образом устроены и клипы. Если ваш клип расположен на главной временной шкале Flash-ролика, вы можете обратиться к нему по имени "toyTruck" ("игрушечный грузовик"). Однако, если ваш клип "toyTruck" расположен внутри другого клипа под названием "toyBox", к нему необходимо будет обратиться следующим образом: "игрушечный грузовик внутри коробки с игрушками", или "toyBox.toyTruck'.
Исходный файл: Levels.fla
На рис. 3.4 изображен похожий случай. Данный ролик в файле Levels.fla.

Рисунок 3.4 Клип "secondMC" включен в клип "firstMC", находящийся на рабочем поле
Файл Levels.fla содержит два клипа. Однако только файл "firstMC" находится на рабочем поле. Клип "secondMC" находится внутри "firstMC". Текстовое окно на рабочем поле и в каждом клипе связано с переменной testvariable Эти текстовые окна отображают значения переменной testvariable на рабочем поле и в клипах "firstMC" и "secondMC" соответственно.
То есть в каждом из клипов и на главной временной шкале (можно сказать в клипе _root) мы определили свою переменную и каждой из них присвоили имя testvariable.
Рабочее поле, а также каждый клип содержат кнопку, увеличивающую значение testvariable. Каждой кнопке назначен следующий код:
on (press) { testVariable++; }
Кнопка изменяет значение переменной testvariable. на уровне того клипа, в котором находится данная кнопка. Кнопка, расположенная на рабочем поле, изменяет переменную testvariable на главном уровне Кнопка в клипе "firstMC" изменяет переменную testvariable в "firstМС", кнопка в "secondMC" - переменную testvariable в "secondMC" .
Следует отметить, что три переменные с именем testvariable. являются тремя разными переменными. Находясь на разных уровнях, они как не связаны друг с другом.
Нажатие одной из кнопок меньшего размера изменяет значение переменной testvariable только на том уровне, где она расположена.
Вы можете изменять значение переменных не только на уровне, где не ходится код, но и на других уровнях при помоши синтаксиса ActionScript. Примером могут служить три кнопки большего размера, расположенные в нижней части экрана.
Все три кнопки находятся на рабочем поле, а не внутри клипов. Первая кнопка изменяет значение testvariable, не указывая определенна клип. В результате изменяется переменная testvariable рабочего поля.
Вторая кнопка указывает переменную testvariable внутри клипа "firstMC". Код выглядит следующим образом:
on (press) {
firstMC.testVariable++ ;
}
В результате изменяется переменная в клипе "firstMC". Для изменения переменной внутри клипа "secondMC", необходимо учитывать, что "secondMC" находится внутри "firstMC" и программе нужно это указать.
on (press) {
firstMC.secondMC.testVariable++;
}
Во всех приводимых до сих пор примерах имена копий клипов указывались прямо в коде. Существует и другой способ обращения к клипам - свойство _root:
_root["firstMC"].testVariable++;
Это удобно, если имя копии клипа содержит пробел, в таком случае данный метод является единственно возможным. Свойство _root используется также при создании более сложного кода, где надо представить имя клипа как строку для неявного указания этого имени. Применение данного метода будет рассмотрено в следующем разделе.
Копирование клипов
Важным аспектом создания игры является умение манипулировать клипами. Но сначала нужно научиться создавать клипы. Хотя во Flash это сделать несложно, вы, возможно, захотите, чтобы ваш код создавал клипы во время воспроизведения ролика.
Представьте себе игру, в которой космические корабли врага атакуют игрока. Приближается один корабль, за ним следующий и т. д. Вместо того чтобы заранее создавать сотни клипов, ваш код может создавать их по мере необходимости.
Существует два способа создания клипов: копирование существующего клипа и создание клипа из эталона, находящегося в библиотеке, но не используемого изначально на рабочем поле.
В первом случае используется функция duplicateMovieClip, при помоши которой создается дубликат существующего клипа. Приведем пример:
firstclip.duplicateMovieClip("newclip",0);
Функция duplicateMovieClip запускается копируемым клипом. Поэтому при ее использовании упоминается имя этого клипа, в данном случае "firstclip". Функция также содержит два параметра: имя новой копии клипа и уровень нового клипа.
Это может немного вас запутать. Термин "уровень" здесь (применительно к команде duplicateMovieClip) означает порядок расположения клипов. В предыдущем же разделе данный термин использовался для описания включения одного клипа в другой.
В случае, если клип создан на уровне 0, как в предыдущем примере, он располагается под клипом уровня 1. Клип уровня 1 находится под клипом уровня 2 и т. д.
Не беспокойтесь, что два клипа окажутся на одном уровне, Flash не позволит это сделать. Достаточно в каждой команде duplicateMovieClip указывать другой номер уровня.
Исходный файл: DuplicateMovieClip.fla
В примере DuplicateMovieClip.fla демонстрируется применение данной команды. В первом и единственном кадре главной временной шкалы пе ременная level имеет значение 0. На рабочем поле находится кнопа "new MC", а также клип "firstclip". Каждый раз при нажатии кнопки выполняется следующий код:
on (press) {
// Дублируем первый клип.
firstclip.duplicateMovieClip("newelip"+level,level);
// Помещаем его в случайную позицию.
_root["newclip"+level]._x = int(Math.random()*550);
_root["newclip"+level]._y = int(Math.random()*400);
// Увеличиваем счетчик.
level++;
}
Обратите внимание, что в коде ActionScript я в первый раз использовал комментарий. Строки комментария начинаются с двух косых черт. Содержание строки, следующей за косыми чертами, полностью игнорируется Flash и предназначено для того, чтобы вы понимали, какое действие выполняет код. Чем длиннее блоки вашего кода, тем больше они нуждаются во вспомогательных комментариях. Комментарии используются для последующего редактирования кода, а также для того, чтобы вашему коллеге было легче его понять.
В данной программе обработки переменная level используется по-разному. Во-первых, для присвоения имени новому клипу (сначала клипу присваивается имя newclip. Переменная также отображает уровень клипа В конце программы значение переменной level увеличивается на 1. Таким образом, следующий создаваемый клип будет называться level1 и располагаться на уровне 1. С помощью функции Math.random () мы задаем будущему клипу случайные координаты в пределах рабочего поля. Обратите внимание, ссылка на клип осуществляется при помощи синтаксической структуры _root []. Другой способ создания новых клипов - использование функции attachMovie. Для выполнения данной функции не требуется, чтобы клип находился на рабочем поле. Он должен просто быть в библиотеке. Однако, если клип находится в библиотеке и не используется на рабочем поле, Flash автоматически не включит его в конечный swf-файл. Для того чтобы клип был включен в конечный файл, его необходимо выбрать в библиотеке и настроить его параметры в диалоговом окне Symbol Linkage Properties, которое вызывается из меню Options. Диалоговое окно изображено на рис. 3.5.

Рисунок 3.5 Диалоговое окно Symbol Linkage Properties позволяет включать клип в swf-файл, даже если он не используется на рабочем поле
В окне следует установить флажок Export for ActionScript (Экспортировать для ActionScript). Затем вы должны придумать имя эталона, на которое будет ссылаться код. Я обычно использую имя эталона из библиотеки.
Исходный файл: AttachMovie.fla
Первым параметром функции attachMovie является имя из диалогового окна Symbol Linkage Properties. Второй параметр - это имя копии клипа на рабочем поле, третий - уровень клипа. Код данной кнопки, содержащийся в файле AttachMovie.fla, за исключением одной строки, полностью совпадает с кодом примера DuplicateMovieClip.fla.
on (press) {
// Дублируем первый клип.
attachMovie("myMovieClip","newclip"+level,level);
// Кладем в случайное место.
_root["newclip" + level]._x = int(Math.random!)*550);
_root["newclip"+level]._y = int(Math.random()*400);
// Увеличиваем счетчик, level++;
}
Исходный файл: RemoveMovieClip.fla
При помоши функции RemoveMovieClip вы можете удалять клипы с рабочего поля. Например, следующий код из файла RemoveMovieClip.fla перед созданием нового клипа удаляет предыдущий:
on (press) {
// Удаляем предыдущий клип.
_root["newclip"+(level-1)].removeMovieClip();
// Дублируем первый клип.
attachMovie("myMovieClip","newelip"+level,level);
// Кладем в случайное место.
_root["newelip"+level],_x=int(Math.random()*550);
_root["newclip"+level]._y=int(Math.randomf)*400);
// Увеличиваем счетчик.
level++;
}
Используя данные приемы, вы можете сделать так, чтобы ваши игры и приложения создавали свои собственные клипы, добавляя и удаляя их с рабочего поля по мере необходимости.
Управление несколькими клипами
Теперь, когда вы научились создавать клипы при помоши ActionScript, рассмотрим способы управления ими. Вы знаете, что можете управлять одним клипом с приписанным ему кодом, а если необходимо, управлять несколькими клипами? Что, если эти клипы ведут себя аналогичным образом?
Поместив клипы на рабочее поле, вы можете копировать код одного клипа и вставлять его в другие. Этот метод имеет несколько недостатков. Во-первых, необходимость копировать и вставлять. Затем, если вы захотите изменить код, вам придется сделать это во всех копиях клипа.
Пересечение объектов.
В игах часто происходят столкновения между различными объектами, причем иногда с весьма разрушительными последствиями. Давайте научимся создавать код, позволяющий отслеживать такие события, как пересечение двух объектов или, например, прохождение курсора над определенным объектом.
Основной способ обнаружения ситуации, в которой два объекта пересекаются или объект закрывает определенную точку экрана, - использовать функцию hitTest. Аргументом функции hitTest могут быть координаты какой-либо точки или ссылка на обьект, например клип, кнопку или текстовое поле.
Давайте начнем с проверки пересечения клипа с точкой. Предположим, вы хотите определить, находится ли курсор над определенным клипом на рабочем поле. Клипу следует назначить следующий код:
onClipEvent (enterFrame) {
if (this.hitTest(_root._xmouse,_root._ymouse,true)) {
this._x = int(Math.random()*550);
this._y = int(Math.random()*400);
}
}
Строка this.hitTest () обозначает, что функция hitTest применяется к текущему клипу. Она включает три параметра: горизонтальное и вертикальное положение мыши, а также булевый параметр (значения true/false). Последний параметр определяет, использует ли Flash для контроля пересечения прямоугольную область, в которой содержится данный клип, или точную форму изображения в клипе. Во втором случае параметр должен быть равен true.
Исходный файл: Runaway.fla
Вышеописанный код рассматривается в примере Runaway.fla. Если установить курсор над клипом, он переместится в случайную точку экрана.
Исходный файл: Collision.fla
Для того чтобы определить, пересекаются ли два клипа, вы можете использовать один параметр - указатель на второй клип. В ролике Collision.fla на рабочем поле находятся два клипа. Клип большего размера называется "target", меньшего - "bullet". За пределами рабочего поля расположен клип "actions" со следующим кодом:
onClipEvent (enterFrame) {
// Выясняем, попала ли пуля в мишень.
if (_root["target"].hitTest(_root["bullet"])) {
// Попадание, увеличиваем цель.
_root["target"]._xscale += 5;
_root["target"]._yscale += 5;
// Убираем пулю.
_root["bullet"]._x = 350;
} else {
// Нет попадания, пуля летит дальше.
_root [ "bullet" ] ._х -= 5;
}
}
Код задает перемещение снаряда на 5 пикселов. Если сталкиваются два клипа, мишень немного увеличивается за счет увеличения масштаба на 5%. Горизонтальная координата снаряда принимает первоначальное значение, и он может опять начинать свое перемещение. Вы научились изменять масштаб клипа и его положение. Далее вы узнаете другие способы, с помошью которых можно изменить внешний вид клипа.
Изменения содержимого экрана с помощью клипов
К сожалению, Flash не позволяет заменить один клип другам на рабочем поле. Единственным выходом будет удалить один клип и создать на его месте другой. Но если внешний вид клипа должен часто изменяться, необходим более быстрый способ.
Таким способом является создание клипа, который содержал бы все возможные состояния объекта. Например, если объектом является космический корабль, в ролик необходимо включить кадры, изображающие: космический корабль с выключенным двигателем, с включенным главным двигателем, включенным левым двигателем, с включенным правым двигателем, а также ряд кадров, представляющих взрывающийся космический корабль.
Исходный файл: Changingimages.fla
Данный пример демонстрируется в файле Changingimages.fla. Кнопки,расположенные слева от клипа, помогают выбрать отображаемую часть клипа. На рис. 3.7 изображен фрагмент ролика.

Рисунок 3.7 Ролик Changingimages.fla позволяет отображать различные вилы одного и того же объекта
Каждая кнопка ролика Changingimages.fla задает перемещение клипа в определенный кадр. Приведем пример кода кнопки Up:
on (press) {
ship.gotoAndStop("up") ;
}
Код кнопки Explode отличается от остальных, он использует команду gotoAndPlay, задающую перемещение клипа к кадру "explode" и продолжение воспроизведения:
on (press) {
ship.gotoAndPlay("explode") ;
}
Клип включает последовательность из восьми кадров, которая начинается с кадра "explode" и изображает взрыв. Последний кадр последовательности содержит команду stop, задающую остановку воспроизведения клипа после взрыва.
Просматривая ролик Changingimages.fla , обратите особое внимание на временную шкалу клипа "ship". Здесь кадры маркированы таким образом, что код использует не номера, а имена кадров.
Ввод команд с клавиатуры
В предыдущем примере каждой части клипа соответствовала одна из пяти кнопок. Хотя основным средством управления во Hash-роликах являются кнопки, иногда в играх используется и прямой ввод с клавиатуры.
Существует два способа ввода с клавиатуры. Первый подразумевает особый вариант использования кнопок. Второй способ предполагает только код, который проверяет нажатие клавиш в определенный момент времени.
Для применения кнопочного метода создайте обычную кнопку Flash. Она не должна представлять из себя ничего особенного, так как будет расположена за пределами рабочего поля. Если кнопке назначен следующий код, она будет реагировать на клавишу "r" и использовать ее для перемещения клипа:
on (keyPress "r") {
circle._x++;
}
Имейте в виду, что событие keyPress чувствительны к регистру. Это значит, что если кнопке назначена клавиша "r", она не будет реагировать на нажатие комбинации Shift+R.
Исходный файл: Keyboardbutton.fla
ДЛЯ обозначения движений лучше использовать клавиши с изображением стрелок, а не буквы. Для указания данных клавиш используется специальный синтаксис. Ниже приведен сценарий, позволяющий пользователю перемешать клип в четырех направлениях. Вы можете также найти данный сценарий в файле Keyboardbutton.fla.
on (keyPress "") {
circle._x++;
on (keyPress "") {
circle._x—-;
on (keyPress "") {
circle._y--;
on (keyPress "") {
circle. _у++;
} }
Клавиши не очень удобно использовать в ситуациях, требующих быстрых и плавных движений. В таких случаях при помощи кодового объекта Key вы сможете проверить, нажата ли кнопка.
Если для проверки нажатия клавиши используется кнопка, при удерживании клавиши пользователем действие будет повторяться. Это происходит потому, что большинство компьютеров запрограммировано на повторение при удерживании клавиши. Время между первым и вторым нажатием одной и той же кнопки, а также между последовательным нажатием разных кнопок определяется параметрами настройки клавиатуры системы пользователя. В играх, где пользователь может удерживать кнопку для повторения действия, не следует полагаться на функциональные возможности клавиатуры. Лучше применять функцию Key. isDown (), которая рассматривается в данном разделе.
Функция Key. isDown () позволяет проверить состояние клавиши. Например, чтобы проверить, нажата ли клавиша "r", используется следующий код:
if (Key.isDown("г") ) {
circle._x++;
}
Исходный файл: Keyisdown.fla
Такой код не может и не должен быть назначен кнопке. Он должен быть назначен клипу "actions", в данном случае в файле Keyisdown.fla. Код находится внутри программы обработки onClipEvent (enterFrame), поэтому проверка происходит в каждом кадре. Код проверяет нажатие клавиш с изображением стрелок, которые обозначаются специальными константами наподобие Key.RIGHT.
onClipEvent(enterFrame) {
if (Key.isDown(Key.RIGHT)) {
_root.circle._x++;
}
if (Key.isDown(Key.LEFT) {
_root.circle._x--;
}
if (Key.isDown(Key.UP)) {
_root.circle._y--;
}
if (Key.isDown(Key.DOWN) {
_root. circle._y++;
}
}
При запуске данного ролика вы обнаружите, что движения круга стали более плавными. Значение частоты смены кадров было увеличено до 120 кадр/сек, максимального количества, которое может обработать компьютер.
Итак, когда же отдать предпочтение кнопке, отзывающейся на нажатие клавиши, а когда объекту Key? Если нажатие клавиши необходимо только для активации события, используйте кнопку. Она будет реагировать на нажатие клавиши в 100% случаев. Функция Key.isDown() отреагирует на нажатие клавиши, только если она вызвана. Поэтому, если пользователь нажмет и тут же отпустит кнопку, нажатие может быть пропущено. Это часто происходит на медленных компьютерах.
Функцию Key.isDown() лучше использовать для контроля движения. В данном случае плавное движение будет продолжаться на протяжении всего времени удерживания клавиши. Функция может воспринимать одновременное нажатие нескольких клавиш, в то время как кнопка реагирует только на нажатие одной клавиши.
Воспроизведение звука
Завершая вводную часть нашего учебника по ActionScript, рассмотрим использование звука. Flash может воспроизводить звуки, помещая их временную шкалу ролика или клипа. Вы также можете запускать воспроизведение звука при помощи команд ActionScript.
Запуск звука из библиотеки представляет собой несколько более сложную процедуру, чем просто вызов одной команды. Прежде всего, необ холимо убедиться, что звук включен в конечный swf-файл. Это можно сделать в диалоговом окне Symbol Linkage Properties. Сам процесс был, рассмотрен на уроке 20 "Управление несколькими клипами". В данной случае предположим, что звук связан с именем "beep".
Воспроизведение звука задается при помощи нескольких строк кода. Сначала надо создать объект типа Sound. Затем объекту необходимо сообщить что "beep" - это звук, который должен воспроизводиться. Потом следует запустить звук. Вот как будет выглядеть код внутри сценария кнопки:
on (press) {
mySound = new Sound();
mySound.attachSound("beep");
mySound.start();
}
Функция start, которая используется со звуками, может включать два параметра. Первый - это задержка времени в секундах перед началом воспроизведения звука. В случае, если вы хотите пропустить первые три секунды, значение параметра будет 3. При обычном воспроизведении устанавливается 0. Вторым аргументом является количество циклов звука. Для воспроизведения 10 звуковых сигналов подряд используется значение 10.
Существует множество возможностей настройки звука. Наиболее важной из них является регулирование громкости. Если звук слишком громкий, вы можете изменить код ActionScript, а не переделывать звук. I
Для настройки громкости, значение которой варьируется от 0 до 100, используется функция setvolume. Ниже приведен тот же самый код, но с уменьшенным вполовину значением громкости:
on (press) {
mySound = new Sound();
mySound.attachSound("beep");
mySound.setVolume(50);
mySound.start();
}
Стоит также отметить функцию set Pan, которая может принимать значение от -100 до 100. Она позволяет контролировать баланс для стереозвуков, при этом -100 соответствует левой колонке, 100 - правой. При воспроизведении в режиме моно звук из одной колонки будет сильнее, чем из другой. Ниже приведен сценарий, задающий воспроизведение звука только из левой колонки:
on (press) {
mySound = new Sound();
mySound.attachSound("beep");
mySound.setPan(-100);
mySound.setVolume(100);
mySound.start();
}
Неудобно лишь то, что когда задается громкость или баланс, их значения остаются неизменными и при воспроизведении следующего звука. Поэтому данные параметры необходимо каждый раз настраивать заново. В противном случае новый звук будет воспроизводиться с настройками предыдущего.
Исходный файл: Sound.fla
Ролик Sound.fla содержит четыре кнопки. Большая кнопка в центре отвечает за обычное воспроизведение звука. Большие кнопки слева и справа предназначены для воспроизведения звука только из левой или из правой колонки. Маленькая кнопка в центре воспроизводит звук с громкостью 50%.
Вы узнаете больше о звуках в разделе "Музыкальный автомат" главы 6 "Игрушки и безделушки", а также в разделе "Музыкальный микшер" главы 7 "Игрушки-конструкторы".
На этом мы закончили изучение основ ActionScript. В следующей главе вы узнаете о таких приемах программирования, как планирование, отладка и тестирование. Затем, начиная с главы 5 "Создание визуальных эффектов", мы начнем рассматривать примеры программ.
Анализ задачи
Важно осознать, что если задача кажется слишком большой, чтобы с ней справиться, по-видимому, она таковой и является. Разбейте ее на более мелкие задачи, и вы найдете решение.
Достоинства
Flash имеет множество преимуществ над другими средами разработки игр. Несмотря на то, что программирование на языках низкого уровня, типа C++ или Java, более эффективно, оно не способно превзойти Flash в следующих областях:
• быстрая разработка - Flash позволяет создавать игры от начала до конца всего за несколько дней или даже часов;
• мультимедиа - Flash дает возможность импортировать и использовать различные типы графических изображений и звуковые форматы. Вы можете сотрудничать с художниками и звуковыми дизайнерами, не заботясь о необходимости конвертации файлов или каком-либо их изменении для использования в игре;
• простота использования - Flash очень прост в использовании. Такие функции как "drag and drop", меню команд ActionScript, панели и диалоговые окна позволяют быстро добавлять и изменять элементы и тратить минимум времени на утомительные процедуры;
• подача результатов вашей работы - несомненно, самым большим преимуществом Hash является способ подачи результатов вашей работы. Благодаря Flash-плагину для браузеров она может быть представлена на Web-странице для просмотра всеми желающими. Кроме того, вы можете создавать автономные проекты (просто отдельные swf-файлы), которые могут быть просмотрены практически на любом компьютере Мае или PC.
Более важно осознать недостатки, а не достоинства Flash. Вы не сможете создать очередной Quake или Age of Empires. С другой стороны, ваша игра будет иметь более широкую аудиторию и возможность более легкого распространения, чем эти крупнобюджетные игры.
Flash и игры
Изначально программа Flash предназначалась не для создания игр, а для подготовки анимаций и интерфейсов Web-сайтов. Возможность создания настоящих игр во Flash появилась только с введением ActionScript.
Фон
В некоторых играх графические изображения занимают весь экран. Другие игры занимают только часть экрана, при этом остается место для красочного фона.
Участниками большинства игр, рассматриваемых в данной книге, являются лисенок и его друзья. В качестве окружающей лисенка обстановки используется фон, изображающий лес и отдельные деревья.
Глобальные и локальные переменные
Имейте в виду, что если перед первым использованием переменной в функции не стоит ключевое слово var, то переменная является глобальной. В случае использования аналогичного имени переменной в другом месте функции ее значение может заменить значение предыдущей переменной. Допустим, вы используете переменную i в цикле for, а затем внутри данного цикла вызываете другую функцию, которая использует переменную i для своего цикла for. В таком случае значения переменных будут наложены друг на друга, и для того чтобы избежать этого, используйте разные имена переменных или синтаксическую структуру var.
Вы узнали много об ActionScript из глав 2 и 3, а также об общих приемах программирования из данной главы. Теперь вы готовы перейти к главе 5 "Создание дизайнерских эффектов при помоши ActionScript" и далее, к более сложным примерам программ на ActionScript.
Имена клипов
Каждый клип, расположенный на рабочем поле, имеет два имени. Имя под которым он включен в библиотеку, не имеет никакого значения вашего кода. В отличие от него имя экземпляра клипа на рабочем поле является крайне важным. Часто разработчики вообще забывают присвоить имена экземплярам клипа.
Изменение графики
Простейшим способом изменения игр для последующего размещения на Web-сайте является изменение графики. Вы можете использовать различные эталоны библиотеки и перерисовывать графические изображения или копировать изображения из ранее созданных Flash-роликов. Не изменяя код и не выполняя программирования, вы можете создавать довольно приличные игры.
Изменение игр, рассматриваемых в данной главе
Одна из причин, по которым стоило купить данную книгу, - тот факт, что вы можете использовать рассматриваемые в ней игры для создания своих собственных. Вы наверняка захотите изменить игры таким образом, чтобы они лучше подходили для вашей задачи и отражали ваш стиль.
Изменение кода ActionScript
В конце большинства примеров данной книги вы найдете советы по улучшению соответствующего проекта. Можно считать их своего рода упражнениями в ходе изучения программирования на ActionScript. Конечно, вы можете использовать и свои идеи по изменению игр.
Однако учтите, что добавление функциональных возможностей или изменение игры требует среднего или продвинутого уровня знаний. В случае, если вы не знаете, как внести необходимое изменение, не спешите продолжать и изучите необходимую информацию. В противном случае игра может не получиться.
Недостатки
Конечно, Flash не является идеальной средой для разработки игр. Ниже приведены причины, усложняющие программирование игр:
• построение вокруг временной шкалы - Flash-ролики представляют собой последовательность кадров на временной шкале. Хотя Flash является идеальной средой для создания анимаций, структура игр противоречит прямолинейному движению по временной шкале от кадра к кадру;
• медленная работа - по сравнению со своим старшим братом, Macromedia Director, Flash недопустимо медленная программа для разработчиков. Это ограничивает применение Flash для создания парных игр и игр-аркад с небольшим количеством простых элементов;
• двумерность - Flash не предусматривает создания трехмерной графики, а большинство игр сейчас использует именно 3D-rpaфику. Хотя некоторые программы способны импортировать 3D. графику во Flash, фактически результат все равно содержит лишь плоские изображения, прорисованные с трехмерных фигур. В настоящее время 3D является общепринятым графическим стандартом для игр. Тем не менее данный стандарт не распространяется на сетевые игры, которые обычно создаются с помощью Flash;
• ограниченный набор свойств - предположим, вы хотите добавить в игру какую-либо функцию и обнаружили, что Flash не может ее обработать. Если бы вы составляли программу на языке программирования более низкого уровня, например C++ или Java, у вас была бы возможность добавить эту новую функцию. Однако Flash - это Flash. Только Macromedia может включать новые функции во Flash. Это значит, что при создании игры необходимо идти на компромисс, особенно если ваша игра выходит за пределы возможностей Flash.
Нижнее подчеркивание
Небольшой ошибкой является пропуск нижнего подчеркивания (_) перед большинством встроенных параметрово Flash. Допустим, у вас есть клип под названием "myMovieClip". Тогда myMovieClip._x будет обозначать его горизонтальное положение, но myMovieClip.х - просто переменную х внутри клипа "myMovieClip".
Объединение игр
Обычным приемом программистов является объелинение двух уже существующих игр целью создания новой. Вы можете попробовать создат такую игру, используя игры данной книги. Однако эта задача требует опыта программирования, поэтому не расстраивайтесь, если все сразу не получится.
Следующий раздел поможет всем, кто собирается изменять игры, избежать распространенных ошибок.
Окно загрузки
Ролики Flash загружаются в браузер пользователя потоком. Это значит, что их воспроизведение начинается только после загрузки первой части ролика и с таким расчетом, что ко времени начала воспроизведения второй части он уже будет полностью загружен. Все происходит aтоматически, хотите вы этого или нет.
Автоматическая загрузка данных хороша для анимации, но не всегда для игр. В большинстве случаев ActionScript контролирует появление элементов на рабочем поле и не контролирует анимационную временную шкалу. Flash недостаточно умная программа, чтобы понимать, какие элементы вам нужны в первую очередь, и часто не загружает их во время передачи данных.
По этой причине в играх следует избегать автоматической загрузки. Лучше сделайте первый кадр или сцену ролика окном загрузки. Окно загрузки отображает сообщение для пользователя и не переходит дальше, пока не будет загружен весь ролик. Это предоставляет вам полный контроль над элементами, которые видит пользователь и не ставит вас в зависимость от того, какие элементы загружены, а какие нет.
Более подробно о создании окон загрузки рассказано в главе "Сложные приемы" .
Окно завершения игры
Очень часто конец игры оформляется в виде специального окна. В некоторых играх в случае выигрыша загружается одно окно, в случае проигрыша - другое. Необязательно игры заканчиваются выигрышем или, проигрышем, некоторые из них завершаются в случае, если игрок истратил все боеприпасы, жизни или время. Иногда окно завершения игры отображает список игроков, набравших самое большое количество очков, и дает игроку возможность внести свое имя в данный список. Создание списка победителей рассматривается в главе "Сложные приемы".
Отладка
Всем программистам приходится отлаживать создаваемые ими программы. Невозможно добиться безупречной работы программы при ее первом запуске. Хороший специалист должен уметь отлаживать программу.
Помимо использования отладчика ActionScript, отладку можно производить различными способами. При пробном воспроизведении ролика в окне Output могут появляться сообщения об ошибках. Иногда этого достаточно, чтобы вы поняли, в каком месте кода у вас проблемы.
Информация о программе может также размещаться в окне Output при помоши команды trace. Она поможет вам отследить определенные моменты программы и значение некоторых переменных в эти моменты.
Если же вы хотите воспользоваться программой отладки, советуем вам изучить соответствующую информацию в руководстве по Flash MX. Программа отладки является простым инструментом, позволяющим отображать значения переменных во время воспроизведения Flash-ролика. Однако она не в состоянии творить чудеса; программа отладки может только помочь вам разобраться в собственном проекте.
Правила программирования
Во время изучения программирования следует придерживаться некоторых правил, которые помогут облегчить вашу работу. Эти правил выполняют программисты всего мира, использующие все языки программирования:
• комментарии - следует приобрести привычку добавлять к коду комментарии. Даже строки, кажущиеся ясными в данный момет могут стать непонятными, если вы вернетесь к ним через месяц;
• имена переменных - используйте имена переменных, отражюшие их назначение. Они дополнят комментарии и помогут понять код, когда вы вернетесь к нему позднее;
• имена функций - все вышесказанное относится и к именам функций. Они должны описывать выполняемые ими действия;
• чем короче, тем лучше - во Flash нет ограничения на длину функции. Тем не менее, если вы напишите функцию длиной в 100 строк, позднее вам будет непросто ее редактировать. Лучше разбить функцию на задачи и поместить каждую задачу в отдельную функцию;
• включайте в код многократно используемые функции - во время программирования не забудьте подумать о том, как можно применить ту или иную функцию к схожей или аналогичной задач другой части вашей программы. Допустим, вам необходима функция, добавляющая одно очко к счету игрока. Постарайтесь использовать в ней параметр , позволяющий добавлять к счету не только одно, но и любое другое количество очков;
• старайтесь обходиться без жесткого кодирования - под жестким кодированием подразумевается включение в ваш код конкретных чисел. Допустим, для описания правой стороны рабочего поля в вашем коде используется значение 550, оно будет жестко закодировано в программу. Если вы решите расширить рабочее поле ас 600 пикселов, вам придется изменять каждое употребление значения 550 в коде. Лучше в самом начале задать переменной под названием screenRightSide значение 550 и использовать эту переменную на протяжении всей программы;
• хорошая организация - хороший программист, несомненно, должен уметь организовывать различные элементы программы. На-пример, функции следует помешать не в разные кадры, а в один кадр вашего ролика. Кроме этого, старайтесь сгруппировать функции согласно выполняемым ими задачам.
Правила
Важным элементом игры являются правила. Во многие игры можно играть и без правил, однако о них стоит позаботиться, так как некоторым людям нравится их читать.
В других играх правила могут располагаться в отдельном окне. Если игра сложная, правила иногда излагаются в нескольких окнах, представляющих своего рода учебник.
Еше один вариант - вообще не включать правила в игру. Правила некоторых моих игр содержатся на отдельной HTML-странице Web-сайта. При этом пользователь получает возможность открыть правила в отдельном окне и просматривать их, не отвлекаясь от игры. Это также позволяет предоставлять правила на других языках.
Программирование
Не думайте, что изучив главу "Введение в ActionScript" и главу "Элементы ActionScript" для создания игр", вы уже научились программировать. Существует разница между умением создавать код на ActionScript и опытом программирования.
Большинству людей программирование дается трудно, мне легко. Но у меня научная степень по вычислительной технике и я занимаюсь программированием уже 18 лет. Не имея аналогичного опыта, не следует ожидать быстрых результатов.
Вот некоторые принципы, руководствуясь которыми, вы сможете научиться программировать. Как и любой навык, программирование требует времени для изучения. Вы обнаружите, что чем больше вы программируете, тем легче оно вам дается.
Распространенные ошибки
Независимо от того, изменяете ли вы игру или создаете свою собственную, время от времени вы будете сталкиваться с ошибками. Обычно это несерьезные ошибки, которые легко обнаружить и исправить. Вот некоторые ошибки, с которыми я столкнулся при создании игр во Flash.
Splice и Slice
Еше одна ошибка - случайное использование в массиве функции slice вместо функции splice, предназначенной для удаления элемента массива. Пропущенное "р" может ускользнуть от вашего взгляда, а разница выполняемых функций приведет к возникновению ошибок.
Свойства связи
Если для создания копий эталона используется команда attachMovie, необходимо выполнить соответствующие настройки в диалоговом окне Symbol Lynkage Properties, в том числе присвоить ему имя. Таким образом, присвоить клипу имя можно тремя способами: в библиотеке, в копии клипа на рабочем поле, а также в диалоговом окне Symbol Linkage Properties.
Тестирование
Следующим этапом отладки является тестирование ваших игр другими людьми. Тестирование является важным аспектом, особенно, если игра разрабатывается вами на профессиональном уровне. Будучи программистом, вы не сможете объективно оценить работу своего детища и его недостатки.
Вы наверняка узнаете много нового, когда кто-нибудь в первый раз начнет играть в вашу игру. Вы даже и не представляли себе, что он будет щелкать по таким элементам. Он может перетаскивать элементы за пределы рабочего поля или помешать туда, где их не должно быть.
Обычно перед официальным представлением широкой аудитории игра проходит два этапа проверки. На первом этапе (альфа-тестирование) игра тестируется вашими коллегами или друзьями. Бета-тестирование осуществляется людьми, не имеющими отношения к вашей компании или сети. На обоих этапах вы должны получать сообщения об обнаруженных проблемах и по мере их исправления выпускать обновленные варианты игры.
К сожалению, часто при синтаксически верном коде программа выдает неожиданные результаты. Например, поскольку Flash не нуждается в специальном объявлении переменных, то он запросто съест имя несуществующего объекта (вы вполне могли ошибиться при вводе имени) и будет честно выполнять все назначенные ему действия
Дефектами программы считаются не только ошибки, но и несоответствуюшее содержание игры, и отсутствующие функции. Постарайтесь максимально усовершенствовать свою игру, прежде чем заявлять о том, что она закончена.
Титульное окно
Титульное окно представляет собой красочную заставку, представляющую игру пользователю. Иногда я позволяю своим иллюстраторам вволю поэкспериментировать, чтобы создать действительно эффектную заставку.
Вспомните старые игровые автоматы 80-х. Хотя графика самой игры могла отображаться большими пикселами, автомат обычно был оформлен детально и красочно. Это один способ представления статичных элементов титульного окна.
Другой способ - расположить часть графических изображений и клипов игры вокруг названия. Используя для заставки графику из игры, вы сможете избежать увеличения размера файла игры.
Уровни клипа
Еще одной распространенной проблемой является место расположения переменной. Например, если переменная включена в сценарий, назначенный клипу, она будет находиться на уровне этого клипа, а не на уровне главной временной шкалы. Для обрашения ко всем переменным вашего ролика используется точечный синтаксис, однако место расположения переменной можно легко забыть.
Вопросы авторских прав
Теперь, зная основы ActionScript, вы планируете заново создать вашу любимую игру 80-х, я прав? А вы когда-нибудь задумывались о том, что она может охраняться авторским правом?
Разместив что-либо на своем Web-сайте или сайте вашей компании, вы становитесь издателем. В издательском деле принято защищать свою работу от копирования. Если вы воссоздадите существующую игру и разместите ее на Web-сайте, на вас могут подать в суд за нарушение закоь об авторских правах.
К вопросу авторских прав разные компании относятся по-разному. Некоторые заявляют о своих правах даже на идеи популярных жанров компьютерных игр. Другие компании не беспокоятся о том, что их игры копируются и даже имеют в точности такие же названия, как и оригиналы.
Если вы считаете, что ваша игра похожа на одну из ранее опубликованных, проконсультируйтесь с юристом. Судя по моему опыту, юристы дают один из двух советов. Они могут объяснить вам, что это непростой вопрос, и вы должны быть осторожны. Вряд ли этот совет принесет пользу. Другим советом будет не рисковать и вообще не публиковат игру. Здесь есть здравый смысл, поскольку вы спрашиваете юриста о том, как избежать проблем, и он советует вам, как это сделать. Тем не менее данный совет не решит вашей проблемы в случае, если вы собираетесь создавать игры.
Первым делом необходимо ознакомиться с игрой, которую вы собираете создавать. Например, разработчиком игры "Othello" является производитель игрушек, которому наверняка не понравится, если вы создадите под тем же названием. Однако игра "Reversy" - это та же игра. "Reversy" считается игрой старого образца, наподобие "Chess" или "Checkers", Вопрос с другими играми более очевиден: "Scabble" запрещено копировать,если у вас нет разрешения владельца. "Backgammon" может свободно распространяться и копироваться. Другое дело - игра "Yahtzee", принадлежашая компании Milton Bradley, хотя ей предшествуют аналогичные игры "Poker Dice Yacht", считающиеся эталоном.
Задача данного раздела - поставить вас в известность о существовании подобной проблемы. Тем не менее, я не могу предложить другого выхода, кроме обращения к юристу.
Имейте в виду, что игры, рассматриваемые в данной книге, предназначены для использования в этом и других вариантах на вашем Web-сайте и в других проектах. Все эти игры являются общими концепциями, наподобие головоломок.
Добавление ребер
Восемь точек куба создают довольно точную иллюзию трехмерного объекта, но вы можете усовершенствовать модель. Если добавить линии для каждого ребра фигуры, она приобретет еше больше сходства с кубом даже когда не вращается.
Во Flash динамические линии создаются на основе библиотечного эталона, содержащего простую линию. Линия начинается в центре клипа и тянется вправо и вниз. Она простирается ровно на 100 пикселов по горизонтали и по вертикали. В панели Properties необходимо установить толщину линии как hairline. На рис. 5.11 изображено основное окно Flash, которое содержит такую линию. Обратите внимание, что шаг сетки составляет 50x50 пикселов.

Рисунок 5.11 Клип простой линии используется для создания динамических линий на рабочем поле
У куба 12 граней, следовательно, вам необходимо 12 линий. Вместо того чтобы задавать координаты х, у и z обоих концов каждой линии, вы можете использовать две точки, уже имеющиеся в массиве points. Каждая линия имеет два параметра: p1 и р2.
// Создаем массив из 12 линий для граней куба,
function makeLinesO {
lines = new Array ();
lines[0] = {pi: 0, p2: 1};
lines[1] = {pi: 1, p2: 2};
lines[2] = {pi: 2, p2: 3};
lines[3] = {pi: 3, p2: 0};
lines[4] = {pi: 4, p2: 5};
lines[5] = {pi: 5, p2: 6};
lines [6] = {pi: 6, p2: 7};
lines[7] = {pi: 7, p2: 4};
iines[8] = {pi: 0, p2: 5};
lines[9] = {pi: 1, p2: 6};
lines [10] = {pi: 2, p2: 7J} ;
lines [11] = {pi: 3, p2: 4J];
for(i=0;i
attachMovie("line","1ine"+i,50+i)
}
}
Вышеописанная функция создает 12 клипов. Каждый клип получает имя linex, где х - номер линии в массиве lines.
Чтобы динамически нарисовать во Flash линию, надо задать положение клипа, который ее содержит, в первой точке, затем измененить масштаб клипа и определить положение конца линии во второй точке. Так как начало линии находится в центре клипа, в первой точке задается ее верхний левый угол. Масштаб определяет протяженность линии по горизонтали и вертикали, поэтому, задав его значение равным разнице координат х и у начальной и конечной точек, вы разместите линию нужным образом.
К примеру, если вы хотите, чтобы ваша линия начиналась в точке с координатами (50,80) и заканчивалась в точке с координатами (170,210), то надо задать первую точку, присвоив переменным _х и _Y значения 50 80 соответственно. Затем вы должны вычислить разницу координат по горизонтали: 170 - 50 = 120. Разница координат по вертикали будет следующей: 210 - 80 = 130. Задав значения переменных _xscale и _yscale равными 120 и 130 соответственно, вы получите линию с начальными координатами (50,80) и конечными координатами (170,210).
// Рисуем грани куба,
function drawLines() {
for(i-0;i
loci = plotPoint(points[lines[i].pi]);
Ioc2 = plotPoint(points[lines[i].p2]);
this["line"+ij._x = locl.x;
this [ "line"+i] ._y = locl.y;
this["line"+i]._xscale = loc2.x-locl.x;
this["line"+i]._yscale = loc2.y-locl.y;
this["line"+i]._alpha = loc1.z+100;
}
}
Важно, чтобы высота и ширина клипа линии была равна 100 пикселам. Тогда масштаб 100% будет соответствовать 100 пикселам по ширине и высоте, 200% - 200 пикселам и т. а. Параметр толщины линии должен быть определен как "hairline", чтобы масштабирование не оказывало никакого влияния на ее толщину. Линия любой другой толщины, например 1, изменит свой масштаб соответственно изменению переменных _xscale и _yscale.
Все, что осталось сделать для того, чтобы к кубу были добавлены грани, - это задать вызов функции makeLines при запуске ролика, а также функцию drawLines из функции reposition. На рис. 5.12 показан полученный результат. Весь ролик вы можете увидеть, запустив файл 3Dcube.fla.

Рисунок 5.12 Трехмерный куб, состоящий из точек и пиний
Другие возможности
Изменив оператор += на -= в последней строке кода, вы заставите спираль вращаться в обратном направлении. Вы можете также изменить способ смены цветов, изменив значения красной, зеленой и синей составляющих.
Вы можете поместить на экран дополнительные пятна, скопировав клип пятна и убедившись, что ему назначен аналогичный сценарий. На экране может быть столько пятен, сколько вы хотите.
На экране также может быть две и более царапины. Различные части вашей анимации могут содержать различное количество царапин и пятен в зависимости от того, лучшего или худшего качества пленку вы хотите сымитировать.
Для создания следа за курсором вы также можете использовать клипы содержащие собственную анимацию. Таким образом вы можете попробовать получить эффект сверкающего пламени или дыма.
Эффект трехмерности
Исходные файлы: 3d.fla, 3dcubepoints.fla, 3dcube.fla, 3dspaceship.fla
Другим часто применяемым специальным эффектом Flash является моделирование небольшого трехмерного объекта. Некоторые разработчики говорят, что Flash не позволяет создавать настоящую трехмерную графику, но это не может сделать ни одна компьютерная программа поскольку компьютерные мониторы двумерные.
Вся компьютерная трехмерная графика - это всего лишь иллюзия. Хотя Flash и ActionScript не могут похвастаться большими возможностями для создания трехмерных объектов, с их помощью нетрудно создать некоторые специальные эффекты. Используя законы тригонометрии, вы можете преобразовать трехмерные координаты в двумерные на экране и смоделировать простые объекты наподобие куба.
К сведению
Частота смены кадров ролика определяет скорость вращения спирали и смены цветов. Максимальная частота во Flash MX -120 кадр/с. Однако следует иметь в виду, что частота смены кадров напрямую зависит от быстродействия компьютера.

Рисунок 5.4 Спираль изменяет цвет и вращается
И пятна и линию лучше поместить справа, за пределами рабочего поля, чтобы их не было видно при запуске ролика. Затем они будут периодически появляться в случайных местах.
Убедитесь в том, что сценарии находятся на своих местах. При воссоздании ролика не стоит полностью полагаться на текст данной книги. В вашем распоряжении имеются примеры. Поскольку ролик состоит из различных элементов, таких как копии клипов, местоположение сценария и имена объектов, рекомендуем вам вначале подготовить ролик на основе примера , и только после этого создавать его самостоятельно с самого начала.
После выполнения данного упражнения у вас должно получиться несколько клипов и сценариев ActionScript, которые вы можете помещать в любую Flash-анимацию, чтобы создать эффект старого кино.
Позиция клипа Letter0 определяет позицию первой буквы конечного текста, поэтому советуем вам внимательнее отнестись к его расположению и немного поэкспериментировать.
Меняя параметр speed, вы можете изменять длину "хвоста". Значение этой переменной также влияет на скорость исполнения ролика, так как если значение speed маленькое, например 1, то программе приходится одновременно управлять сотней клипов. Другие возможности
Объект Color
Объект Color предназначен для изменения цветов клипа. Его можно представить как набор функций, позволяющих узнавать и управлять цветами клипа.
Сначала надо создать объект Color, связанный с клипом, который вы собираетесь изменять. Это можно сделать следующим образом:
myColorObject = new Color("myMovieClipName");
Объекты наподобие Color построены по образу телевизионного пульта управления. Клип можно представить как телевизор, а объект Color как особый пульт управления, предназначенный для настройки цветовых параметров изображения. Методы объекта Color используются аналогично кнопкам пульта управления.
Существует два способа определения и изменения цветового объекта. Первый - это непосредственно определить цвет при помощи двух строк кода. Сначала создайте новый flash-ролик и поместите на рабочее noле один клип. Назовите копию клипа "myMovieClip". Затем поместите следующий сценарий в главную временную шкалу:
myColorObject = new Color("myMovieClip");
trace(myColorObject.getRGB()).toString());
He забудьте o том, что существует различие между именем эталона клипа в библиотеке и именем конкретного экземпляра клипа на рабочем поле. ActionScript всегда ссылается на имя экземпляра клипа. Имя в библиотеке предназначено исключительно для организационных целей
Во время тестирования ролика автоматически откроется окно Output, в котором будет содержаться значение " 0". Это результат выполнения команды trace.
Функция toString преобразует многие типы ActionScript, например числовые в строку текста. Она, например, удобна для преобразования цветов в числовые значения для вывода при помоши команды trace.
Более интересный результат.можно получить, изменяя цвет ролика. Чтобы это сделать, выделите клип и на панели Properties выберите в выпадающем кэшем меню Color пункт Advanced, после чего нажмите кнопку Settings. В появившемся окне Advanced Effect введите значение 128 в поля R,G и В. Введите значение 128 в поля R, G и В (рис. 5.3) в правой колонке. В левой колонке выставьте значение 0.

Рисунок 5. 3 Панель Advanced Effect предназначена для изменения цвета клипа
Теперь при тестировании ролика в итоговое окно будет помешено значение 8421504, что соответствует значениям 128 полей R, G и В. Немного изменив функцию tostring, вы вместо десятичного значения получите шестнадцатеричное. Оно будет выглядеть как значение RGB, используемое дизайнерами для задания цветов.
myColorObject = new Color("myMovieClip");
trace((myColorObject.getRGB()).toString(16));
Описание new позволяет создавать новые копии объектов наподобие объекта color. Оно также используется для создания новых массивов и ваших собственных объектных конструкций. Если на данном этапе оно не понятно, не беспокойтесь. Для того чтобы использовать описание new, полное понимание не требуется.
Результатом в данном случае является значение 808080, шестнадцатеричное число, представляющее собой средний серый цвет (красная,'зеленая и синяя составляющие, которые имеют значение 128, среднее между 0 и 255). Значение 16 в качестве параметра функции toString () задает преобразование числовых значений в шестнссшатеричные. Теперь, когда вы умеете получать RGB-значение цвета клипа, следующим шагом будет его изменение. Это можно сделать при помощи функции set RGB. Она имеет только один параметр: шестнадцатеричное значение, которое вы хотите использовать. Приведем пример с тем же роликом, но с несколько измененным кодом:
myColorObject = new Color("myMovieClip");
myColorObject.setRGB(OxFFOOOO);
Сочетание Ox указывает, что за ним следует шестнадцатеричное число. Приведенное в коде число FF0000 соответствует красному цвету. При запуске цвет ролика изменится на красный независимо от исходного. Действие этих двух строк кода продемонстрировано в примере Color-change. fla
Перемещение букв
Исходный файл: Textfly.fla
Во многих Flash-роликах по экрану перемешается текст. Существует множество способов создания этого эффекта, некоторые из них проиллюстрированы примерами.
Подготовка ролика
Ролик содержит несколько кнопок. Каждая кнопка представляет собой отдельный ролик с кнрпкой внутри. Из одного библиотечного эталона кнопки я создал пять разных клипов. В каждый клип поместил одну и ту же кнопку, но разный текст.
Кнопка может иметь любую форму и цвет. Я использовал классический стиль, поскольку хотел просто продемонстрировать работу сценария.
В данном ролике будет использоваться один элемент - спиральная фигура. Поместите его в центр рабочего поля. Начальный цвет спирали должен быть белым, а фоновый - черным. Ролик будет состоять из одного сценария, назначенного клипу с изобрел жением спирали. Переменная п, участвующая в сценарии, содержит способ изменения цвета. Значение цвета будет соответствовать числу из предыдущего списка. Так, например, если n будет равно 3, значение красной составляющей увеличится. Значение переменной п сначала равно 1, затем увеличивается до 6 и далее цикл повторяется. Ниже приведена часть кода с последовательностью if...then, которая использует значение переменной n и изменяет объект преобразования цвета.
if (n == 1) {
colorTransform.rb -= 5;
if (colorTransform.rb ==0) n = 2;
} else if (n == 2) {
colorTransform.bb -= 5;
if (colorTransform.bb ==0) n = 3;
} else if (n == 3) {
colorTransform.rb += 5;
if (colorTransform.rb == 255) n = 4;
} else if (n == 4) {
colorTransform.gb -= 5;
if (colorTransform.gb == 0) n = 5;
} else if (n == 5) {
colorTransform.bb += 5;
if (colorTransform.bb == 255) n = 6;
} else if (n == 6) {
colorTransform.gb += 5;
if (colorTransform.gb == 255) n = 1;
}
Оператор += используется для прибавления к переменной определенного числа. Например, код n += 5 прибавляет 5 к значению n. тот код аналогичен коду n = n + 5. Оператор =- используется для вычитания определенного числа из переменной.
Значение переменной n проверяется в каждой части выражения if...then. В случае совпадения одна из трех цветовых составляющих объекта colorTransform изменяется. После окончания изменений, сама переменная п меняет свое значение на следующие. Полная профамма представляет собой обычный клип ActionScript с функциями onClipEvent (load) и onClipEvent (enterFrame). Первая вводит объекты цвета и преобразования, вторая выполняет постепенное изменение цветов. Кроме того, мы сделаем так, чтобы клип вращался. Вращение достигается постепенным увеличением значения параметра _rotation.
В качестве примера использования случайных чисел создадим один из популярных Flash-эффектов: сымитируем старую кинопленку. Обычно данный эффект достигается средствами анимации. Аниматор помещает небольшие точки и трещинки в различные кадры ролика, а также показывает линию, проходящую вдоль ролика и представляющую царапину на пленке.
Все эти эффекты легко создать в ActionScript. К примеру, царапину можно создать, поместив вдоль одной стороны ролика белую вертикальную линию.
Для того чтобы применить знания о случайных числах, вам прежде всего необходимо какое-нибудь исходное изображение, на которое будут накладываться царапины и пятна.
На рис. 5.5 показан фрагмент исходного ролика. В этом ролике пропеллер самолета вращается, а лиса моргает. Возможно, ваш ролик будет содержать больше анимации.

Рисунок 5.5 Простой анимационный ролик, использующий случайные пятна и царапины для создания эффекта старого кино
Помимо фонового изображения вам понадобятся клипы пятен и царапин для размещения поверх ролика. В примере Oldfilm.fla царапин представляет собой простую вертикальную линию внутри клипа. Пятно это небольшой овал внутри другого клипа.
Ролик включает графическое изображение, расположенное в центре экрана и совершенно не зависящее от текстового эффекта. Внутри ролика находится один клип, содержащий букву "А". Клип был создан из небольшого текстового окна. В панели Properties ему было назначено свойство Dynamic Text и присвоено имя переменной letterText (рис. 5.8).

Рисунок 5.8 В панели Properties вы можете назначить текстовой области свойство Dynamic Text и присвоить ей имя переменной
Затем текстовое поле преобразуется в клип при помощи команды Insert -> Convert To Symbol. Копия эталона получает имя letter0 и помешается в то место, где находится первая буква фразы, в данном случае в нижний левый угол.
Создадим простой клип с кружочком внутри. Цвет и размер вы может выбрать по своему усмотрению. В нашем примере мы сделали темно-голубую окружность диаметром 20 пикселов. Клипу присвоено имя "Cursor Trail" (След курсора), в панели Linkage Properties выставлен флажок Export for ActionScript и присвоено имя связи CursorTrail.
Теперь создадим клип с надписью "Actions". Поместим его вне пределов рабочей области. Этот клип будет использоваться только как носитель кода, поэтому его содержание может быть любым. Вы можете даже не создавать внутри него никаких изображений или текста - тогда на экране он будет отображаться в виде маленького кружочка.
В описываемых ниже примерах используются только точки и линии. Создать точку легко, однако линия должна соответствовать определенным условиям. Подробное описание приводится ниже.
Подход
Каждая кнопка реагирует на наведение и снятие курсора. При наведении курсора на кнопку обработчик получит новое значение масштаба. Если в начальный момент времени масштаб клипа (с кнопкой внутри) составляет 100%, то новое значение будет, например, 150%.
С каждым кадром сценарий будет постепенно изменять текущий масштаб: от 100% до 150% с шагом 10%.
После того как пользователь уберет курсор с кнопки, эффект будет обратным. Новое значение будет равно 100%, и с каждым кадром кнопка будет уменьшаться на 10%, пока не достигнет этого значения.
Во Flash 5 существует два способа генерирования случайных чисел. Первый - включить в код функцию Random, которая была в четвертой версии
программы. Эта функция выдает значение в диапазоне от 0 до значения,на единицу меньшего, чем аргумент. К примеру, функция Random (5) выдаст значение от 0 до 4.
Во Flash 5 появилась функция Math, random (). Возможно, что в следуюших версиях Flash функции Random уже не будет. Функщ Math.random() выдает число с плавающей запятой от 0,0 до 1,0.
Чтобы получить значение вне диапазона [0..1], результат функции Math. Random () можно умножить на какое-нибудь число. Например, умножение результата на 500 даст значение в диапазоне от 0,0 до 500,0. Функция int округляет результат в меньшую сторону. Использование этой функции в нашем случае позволит получить целое значение в диапазоне от 0 до 499. Приведем пример:
n = int(Math.random()*500);
Следующая короткая функция перемешает клип в случайное место экрана, имеющего размер 550x400.
onClipEvent(load) {
this._x = Math.random()*550;
this._y = Math.random()*400;
}
Использование вышеприведенной функции демонстрируется в ролике Randomlocation.fla. Запустите файл несколько раз, чтобы убедиться, что ролик каждый раз перемещается в другое место экрана.
Следующим шагом является создание случайных чисел и их использование для периодичности внесения хаотичности в ролик. Нижеприведенный сценарий перемешает клип в случайном направлении. Переменные dx и dy принимают значения в интервале от -5 до 5 и задают величину изменения координат клипа _х и _у соответственно (фактически dx и dy определяют скорость перемещения клипа). Переменные dx и dy изменяют свои значения в случайные моменты времени.
onClipEvent(load) {
dx = Math.random()*10-5;
dy = Math.random О*10-5;
}
onClipEvent(enterFrame) {
this._x += dx;
this._y += dy;
if (Math.random()> .
9){
dx = Math.random()* 10-5 ;
dy = Math.random 0*10-5;
}
}
Действие этого сценария демонстрируется в ролике Randommovement.fla. Эллипс перемещается по экрану случайным образом. Он даже может покинуть пределы рабочего поля, так как никаких ограничений в коде не задано.
Ролик создается следующим образом: текст делится на отдельные буквы каждая из которых представляет собой отдельный клип. Затем из случайных мест на экране эти клипы перемешаются в позиции, соответствующие исходному тексту.
Для того чтобы понять, как используются трехмерные координаты, вам необходимо знать основы аналитической геометрии. Это один из самых трудных разделов данной книги, поэтому, если изучение математики вас не привлекает, вы можете пропустить его и перейти к следующей главе.
С помошью ActionScript можно изменить большинство свойств клипов, которые находятся на рабочем поле. В некоторых случаях свойство можно изменить напрямую, в других случаях, например при смене цветов, необходимо использовать функции.
Окружности являются клипами, которые создаются и помещаются в опре деленную точку экрана в течение работы программы. В коде хранятся все существующие клипы. При каждом обращении к кадру программе просматривает массив, уменьшая размер и увеличивая прозрачность каждого клипа. Когда клип с окружностью становится невидимым, он удаляется; также удаляется соответствующий элемент массива.
Преобразование координат
Местоположение объектов на экране определяется двумя координатами: х и у. Объекты в трехмерном пространстве должны иметь три координаты: х, у и z. Последняя определяет глубину.
Для отображения объектов на рабочем поле необходима функция, преобразующая х, у и z в экранные координаты х и у. Кроме того, вы будете наклонять и вращать объекты. Поэтому функция преобразования должна учитывать базовые наклоны и вращение.
Учтите, что это самый сложный сценарий из тех, которые мы до сих пор рассматривали и, возможно, из всех сценариев данной книги.
Математическая функция Math.atan (arctg, арктангенс) используется для преобразования координат в угол, а функции Math.sin и Math.cos - для преобразования значения углов обратно в координаты. Таким o6разом, координаты точки преобразуются в угол и расстояние от центра плоскости. Затем точка поворачивается и вновь преобразуется в координаты. Данное действие выполняется один раз для вращения и один раз для наклона. В результате вы получите координаты х и у, которые можно использовать на экране компьютера.
Комментарии, содержащиеся в нижеприведенном коде, объясняют, какое действие выполняет каждая его часть. Затем приводятся пошаговые объяснения.
// Переводим трехмерные координаты в координаты на экране
// (делаем проекцию).
function plotPoint(object) {
(1) //Берем координаты объекта.
х = object.x;
у = object.у
z = object.z;
(2) // Вычисляем расстояние от центра, radius = Math.sqrt (x*x+y*y);
(3) // Вычисляем первый угол.
if (х == 0) angle = Math.atan(1000000);
else angle = Math.atan(y/x);
if (x < 0) angle += Math.PI;
(4) // Поворачиваем объект,
angle += rotation;
(5) // Вычисляем новые координаты,
realx = radius*Math.cos(angle);
realz = radius*Math.sin(angle);
realy = z;
(6) // Определяем новое расстояние от центра,
radius = Math.sqrt(realy*realy+realz*realz);
(7) // Вычисляем второй угол.
if (realz == 0) angle = Math.atan(1000000);
else angle = Math.atan(realy/realz);
if (realz < 0) angle += Math.PI;
(8) // Добавляем угол наклона сечения,
angle += plane;
(9) // Вычисляем координаты для экрана,
screenx = realx;
screeny = radius*Math.sin(angle);
screenz = radius*Math.cos(angle);
(10) // Центрируем положение объекта. screenx += 27 5; screeny += 200; (11) // Возвращаем новые координаты. return({х:screenx,y:screeny,z:screenz});
Интересно, что Flash распознает понятие бесконечности. Так, выражение Math.atan(1/0) будет вычислено с результатом 1,5707963267949, то есть Pi/2!
Функция Math.atan() преобразует линию в угол в радианах. Необходимо указать значение разницы между начальной и конечной точками линии по вертикали, разделенное на значение этой же разницы по горизонтали. Например, если значения координат начальной и конечной точек линии соответственно равны (200, 200) и (275, 250), то, . чтобы получить угол, необходимо записать Math, atan (75/50). Результатом будет значение .9828 радиан, что составляет примерно 56 градусов. В действительности функция Math.atan () немного сложнее, однако данный пример позволит вам создать общее представление о ней.
Опишем каждый шаг вышеприведенного кода: (1) Задаются координаты х, у и z объекта.
(2) Вычисляется расстояние на плоскости ху от центра координат до проекции объекта на плоскость.
(3) Определяется угол на плоскости ху.
(4) Значение угла увеличивается на величину поворота объекта.
(5) Задаются новые координаты х, у и z с учетом изменения угла.
(6) Задается расстояние от центра координат до объекта на плоскости yz.
(7) Определяется угол на плоскости yz.
(8) Задается наклон плоскости.
(9) Задаются новые координаты х, у и z с учетом наклона.
(10) Центр новых координат имеет значение 0. Для корректировки к ним прибавляется действительное значение центра экрана (в данном случае (275, 200)).
(11)Теперь координаты х и у могут использоваться для отображает объекта на экране. С помощью координаты z можно также снизить яркость объектов, которые должны казаться расположеными дальше от пользователя.
Функция plotPoint преобразует точки с трехмерными координатами в точки с двумерными координатами при помощи ортогональной проекции. Это означает, что перспектива здесь не используется, и объекты находящиеся на дальнем плане, не уменьшаются. Это подходит для моделирования небольших объектов и специальных эффектов, но не годится для создания больших трехмерных сцен.
След от курсора
Исходный файл: Cursortrail.fla
Рассмотрим спецэффект, создание которого невозможно без использования ActionScript. В нашем примере, когда пользователь перемещает мышь, за курсором остается характерный шлейф, состоящий из тающих копий изображения, привязанного к курсору.
На рис. 5.9 можно увидеть пример этого эффекта. Каждая из окружностей показывает предыдущую позицию курсора. Чем раньше создана окружность, тем она меньше и светлее.

Рисунок 5.9 Оставляя копии клипа в позиции, в которой только что находился курсор, можно создать след, тянущийся за курсором
Случайность и эффект старого кино
Исходные файлы: Randomlocation.fla, Randommovement.fla, Oldfilm.fla
Используя Flash исключительно в качестве инструмента анимации, можно добиться поразительных эффектов, но каждый раз анимация будет воспроизводиться одинаково. ActionScript имеет алгоритм выбора случайных чисел, благодаря чему в содержание ролика можно вносить элемент некой непредсказуемости.
Создание кода
В ролике используется два типа сценариев: назначенные кнопкам и назначенные клипам. Первый тип сценария назначен кнопке, находящейся в клипе. Сценарий, назначенный кнопке, реагирует на события мыши, происходящие именно с этой кнопкой. Такие сценарии - обработчики событий - мы уже рассматривали в уроке 6 главы 2, они реагируют на различные события и в случае кнопки задаются конструкцией on () { ... }.
Сценарий кнопки включает три различных обработчика, двумя из которых являются on (rollover) и on (rollout). Они устанавливают значение переменной newscale равным новому масштабу для увеличения или уменьшения кнопки.
Ниже приведен сценарий для кнопки "Home".
on (rollover) {
// Задаем новый размер для увеличения,
newscale = 150;
} on (rollout) {
// Задаем новый размер для уменьшения.
newscale = 100;
}
on (release) {
// Код, исполняемый при нажатии на кнопку.
trace("Home");
}
С помощью конструкции on в сценарии кнопок вводятся фрагменты кода, выполняемые после определенных событий. Такими событиями могут быть press, release, releaseOutside, rollover, dragOver, dragOut и keypress.
Каждый из трех обработчиков в вышеприведенном листинге содержит строку кода, выполняемого после определенного события кнопки, пример, когда пользователь нажимает и отпускает кнопку, выполняет команда trace. При этом слово "Home" помешается в окно Output.
На самом деле в таких случаях обычно используется команда getURl которая сообшает браузеру, что нужно перейти к новой странице. Команда trace приведена здесь только в качестве примера.
Переменная newscale является индивидуально задаваемой переменной и используется для хранения значения задаваемого масштаба клипа. Когда пользователь наводит курсор мыши на кнопку, ее размер увеличивается 150%. Когда он убирает курсор с кнопки, размер возврашается к 100%
Сценарий клипа помешается на один уровень выше, чем сценарий кнопки. На диаграмме (рис. 5.2) изображена главная временная шкала, клип содержащий кнопку, а также два сценария.
Сначала напишем код для царапины. Поместите копию клипа царапины на рабочее поле и назначьте ему следующий сценарий:
onClipEvent(load) {
wanderAmount = 300;
leftLimit = 10;
rightLimit = 540;
chanceOfJump = 50;
xPosition = 275;
speed = 10;
chanceOfChange = 0;
}
onClipEvent(enterFrame) {
xPosition += speed;
this._x = xPosition;
chanceOfChange++; if ((Math.random()*wanderAmount < chanceOfChange)
or (xPosition < leftLimit) or (xPosition > rightLimit)) {
speed = -speed;
chanceOfChange = 0;
}
if (Math.random()*chanceOfJump == 1) {
xPosition = Math.random()*(rightLimit-leftLimit)+leftLimit;
}
}
При вычислении результата математических функций с числами Flash осуществляет операции в следующем порядке: умножение и деление 8 выполняются перед сложением и вычитанием. К примеру, 2x3+4 будет равно 10. Лля изменения порядка выполнения операций необходимо использовать скобки. Например, 2х(3+4) будет равно 14.
Первая часть сценария вводит некоторые переменные. Переменные leftLimit и rightLimit описывают границы линии по горизонтали. Код не позволит ей выйти за пределы этих значений. Переменная speed определяет, насколько перемещается линия в каждом кадре. Остальные переменные задают изменения анимации.
В каждом цикле кадра горизонтальная позиция, xPosition, клипа изменяется с помощью переменной speed. Она задает перемещение клипа на 10 пикселов влево или вправо. Переменная chanceOf change увеличивается и о пределяет вероятность изменения. В случае, если переменная равна 1, существует один шанс из 300 (около 0,33%), что изменение произойдет в данный момент. К тому времени, когда переменная chanceOf Change примет значение 150, вероятность изменения составит 150 из 300 или 50%. Это хороший способ управления каким-либо событием, при котором оно происходит не слишком часто и не слишком редко. С помощью переменной chanceOf Change создается иллюзия случайности.
В данном случае "изменение" обозначает смену направления. Оно осуществляется путем изменения положительного значения переменной speed на отрицательное или наоборот. Изменение также происходит, если линия достигает правой или левой горизонтальной границы.
Другой вид изменения определяется переменной chanceOf Jump и представляет собой перемещение линии в совершенно другое место. Настоящие царапины на пленке появляются в разных местах, и такое перемещение делает ролик более реалистичным.
В процессе выполнения программы из одного клипа создается несколько его экземпляров. В каждом новом цикле при помощи функции duplitcateMovieClip создается новый экземпляр клипа для каждой из букв. После создания каждого экземпляра в него вводятся переменные еndx и endy, задающие окончательную позицию букв в анимации. Значение переменной endy соответствует позиции _у клипа Letter0, значение переменной endx увеличивается слева направо.
Сценарий создает новые копии клипа для букв начиная с той, которая идет под номером 1. Первая буква (она имеет номер 0) использует существующий клип Letter0.
text = "Introducing: Flashy the Fox!";
for (i=0;i
if (i > 0) duplicateMovieClip("Letter0","letter"+i,i);
this["letter"+i].letterText = text.charAt(i);
this["letter"+i].endx = this["Letter0"]._x + i*19;
this["letter"+i].endy = this["Letter0"]._y;
}
Функция charAt выбирает из строки букву, расположенную в определенной позиции. Первый символ строки имеет номер 0. Для того чтобы выделить подстроку, используйте функцию substr.
Команда for позволяет создать небольшой цикл. Код внутри цикла выполняется заданное количество раз. Первый параметр после команды for используется для задания переменной. Второй параметр необходим для проверки, которая осуществляется перед каждым циклом и определяет, надо ли его продолжать. Третьим и последним параметром является команда, выполняемая в каждом цикле. Например, строка for (i=0; i< text.length; i++) обозначает, что переменная i начиная со значения 0 увеличивается на единицу в каждом цикле, и цикл будет продолжаться до тех пор, пока значение i меньше числа символов в тексте
Число 19 в конце пятой строки обозначает, что расстояние между буквами составляет 19 пикселов. Это значение устанавливается в зависимости от используемого вами типа и размера шрифта.
При создании данного эффекта лучше использовать моноширинный шрифт, в котором все буквы имеют одинаковую ширину, например Monaco, Courier и Courier New. В противном случае такие буквы, как "w" и "l", могут значительно отличаться по ширине. Использование шрифтов с различной шириной букв в рассматриваемом коде может привести к "склеиванию" символов.
Наш "actions"-клип содержит два обработчика onClipEvent. Первый включается в начале ролика и создает пустой массив, чтобы содержать ссылки на клипы, образующие хвост. Он также устанавливает счетчику trailNum значение ноль. Эта переменная содержит значение номера следующего клипа, который вы создадите.
Переменная speed определяет как быстро клипы, составляющие "хвост", будут уменьшаться в размерах и таять.
On ClipEvent(load) {
// Создаем массив,
trail = new Array();
trailNum = 0;
// Меньшее значение переменной соответствует меньшей
// скорости.
speed = 2;
}
Следующий обработчик начинается с создания экземпляра клипа. Каждому клипу присваивается уникальное имя вида cursor trail + trailNum Переменная trailNum используется также для определения уровня очередного клипа.
On ClipEvent(enterFrame) {
// Создаем очередной клип.
var mc=_root.attachMovie("cursor trail","cursor trail" + trailNum,trailNum);
}
Созданный клип помешаем в текущую позицию курсора.
//Устанавливаем позицию.
mc._x = _root._xmouse;
mс._у = _root._ymouse,
Указатель на новый клип добавляется в массив trail. Затем значение trailNum увеличивается на единицу.
// Добавляем указатель в массив. trail.push(mc);
trailNum++;
С помощью цикла в остальной части кода происходит обращение ко всем клипам массива trail. Размер и прозрачность каждого клипа изменяются на величину speed. Когда свойство _alpha текущего клипа становится меньше либо равно нулю, этот клип удаляется из массива и ролика в целом.
// Обращаемся к существующим клипам,
for (var i=trail.lenght-1; i>=0; i--) {
// Уменьшаем свойства _alpha и размер клипа,
trail[i]._alpha -= speed;
trail[i]._xscale -= speed;
trail[i]._yscale -= speed;
// Удаляем клип, когда он становится невидимым,
if (trail[i]._alpha
// Удаляем указатель из массива.
trail.splice(0, 1);
// Удаляем клип.
trail [i]. RemoveMovieClip();
}
}
}
Обратите внимание, что массив сканируется от конца к началу. Это сделано потому, что из массива время от времени удаляются элементы, бы массив сканировался от начала к концу, то при удалении элемента возникала бы путаница в порядке следования элементов. Например, если удалить первый элемент, то первым элементом станет второй. Тогда на следующем шаге цикла произойдет обращение к следующему за вторь элементу, то есть к третьему. Таким образом, второй элемент массу окажется пропущенным.
В следующих разделах описывается пошаговое создание трехмерных моделей в Flash. Начнем с кода, преобразующего трехмерные координаты в двумерные экранные координаты.
Трансформация цветов
Более универсальным способом изменения цвета является использование метода setTransform() объекта Color. Аргументом метода set-Transform является объект, содержащий восемь параметров цвета. Параметры rb, gb и bb задают относительное смещение в процентах (от -100% до 100%) для красной, зеленой и синей составляющих цвета соответственно. Параметры rb, gb и bb задают абсолютное (от -255 до 255) значение цветов. Последние два параметра - аа и ab определяют значение свойства _alpha (прозрачность) клипа. На рис. 5.3 изображены все шесть составляющих, плюс два значения преобразующих альфа-канал (прозрачность изображения). Объект преобразования цвета может содержать различные значения каждой из восьми составляющих. Эти значения задаются путем создания новой переменной-объекта. Приведем пример:
myColourTransform = {rb:255, bb:0, gb:0};
Данный объект задает изменение цвета любого цветового объекта на красный. Он включает три параметра: абсолютные значения красного, зеленого и синего цветов. Кроме того, вы можете задавать относительное смешение при помоши параметров rа, gа и bа. Имея объект преобразования цвета и цветовой объект, можно изменять цвет клипа. Следующие три строки изменят цвет клипа на красный:
myColor'= new Color("myMovieClip");
myColorTransform = (rb:255, bb:0, gb:0);
myColor.setTransform(myColorTransform);
В данном примере выполняется то же действие, что и в предыдущем, но другим способом. Преимущество функции setTransform над функцией setRGB состоит в большем контроле над значениями цветов. Например, числа, задаюшие цвет, могут быть переменными ActionScript, а не жестко закодированными числовыми значениями. Кроме того, эти значения могут периодически изменяться, тем самым периодически изменяя цвет объекта. Следующий клип изменяет значение красного цвета клипа от 0 до 255. В результате клип начинается с изображения черного эллипса, который затем постепенно меняет свой цвет на красный. Для создания цветового объекта и объекта трансформации цвета используется событие load. Там же создается переменная n. Следующее за ним событие enterFrame используется для преобразования цвета, применения преобразования к клипу и увеличения значения переменной n.
onClipEvent(load) {
myColor = new Color(this);
myColorTransform = {rb:255, bb:0, gb:0};
n = 0;
onClipEvent(enterFrame) {
myColorTransform.rb = n;
myColor.setTransform(myColorTransform);
n++;
}
Оператор ++ увеличивает значение переменной на единицу. Таким образом, если значение n равно 7, то строка n++ увеличивает его до 8. Для уменьшения значения используется оператор --.
В данном примере значение переменной n, описывающей красный цвет, изменяется от 0 до 255. При достижении максимального значения 255 цвет больше не меняется. Применение сценария демонстрируется в ролике Gradualtransform.fla. Вся эта информация о цветах и преобразовании может использоваться для создания специальных эффектов. Давайте попробуем сделать что-нибудь более интересное. Возьмем основной пример данного раздела и сделаем так, чтобы клип по очереди изменял свой цвет на один из цветов радуги. Для этого необходимо изменить красную, зеленую и синюю составляющие. Здесь будет использоваться та же самая функция setTransform, однако алгоритм изменения значений по сравнению с предыдущим примером будет более сложным. В качестве исходного для красного, зеленого и синего цветов берется значение 255, которое изменяется следующим образом:
1. Значение красного цвета уменьшается до 0.
2. Значение синего цвета уменьшается до 0.
3. Значение красного цвета увеличивается до 255.
4. Значение зеленого цвета уменьшается до 0.
5. Значение синего цвета увеличивается до 255.
6. Значение зеленого цвета увеличивается до 255.
При этом цвета белый, циан (cyan), зеленый, желтый, красный, фуксин (magenta), белый будут плавно превращаться из одного в другой в указанной последовательности. В ней участвуют все цвета, кроме чистогo синего. Так мы создадим изменяющую цвет спираль.
Углы куба
Теперь приступим к созданию восьми вершин куба. Данные о каждой вершине будем хранить в объекте со свойствами х, у и z. Весь список объектов хранится в массиве.
// Создаем массив из 8 точек для вершин куба,
function makePoints() {
points = new Array();
points[0] = {x: 30, y: 30, z: 30};
points[1] = {x: -30, y: 30, z: 30};
points[2] = {x: -30, y: -30, z: 30};
points[3] = {x: 30, y: -30, z: 30};
points[4] = {x: 30, y: -30, z: -30};
points[5] = {x: 30, y: 30, z: -30};
points[6] = {x: -30, y: 30, z: -30};
points[7] = {x: -30, y: -30, z: -30};
// Создаем восемь клипов для вершин куба,
for(i=0;i
attachMovie( "point", "point"+i, i )
}
}
Данная функция создает восемь клипов из эталона, хранящегося в библиотеке. Имя каждого клипа состоит из слова "point" и числа от 0 до 7. Число соответствует точке массива, которую представляет клип.
Команда attachMovie создает новый клип из эталона, хранящегося в библиотеке. Однако для того, чтобы его можно было воспроизвести во Flash player или на Web-странице, необходимо назначить ему свойство Export for ActionScript. Это можно сделать, выбрав команду Options -> Linkage в окне Library. Вы также должны назначить клипу идентификатор. В данном случае назовем его "point".
Кроме точек и функции, преобразующей их координаты в экранное представление, необходимо ввести небольшую функцию, которая бы соединяла линиями полученные точки. Помимо параметров_х и_у каждой точки клипа, задается также параметр _alpha, описывающий уменьшение яркости точек по мере их удаления вглубь экрана.
// Устанавливаем координаты точек и их яркость на экране,
function drawPoints() {
for(i=0;i
loc = plotPoint(points[i]);
this["point"+i]._x = loc.x;
this["point"+i]._y = loc.y;
this["point"+i]._alpha = loc.z+100;
}
}
Все вышеупомянутые функции должны помешаться в главную временную шкалу. Следующие строки вводят модель и подготавливают переменную rotation.
// Вызываем функцию инициализации и останавливаем
// воспроизведение ролика в этом кадре,
rotation = 0;
makePoints();
stop();
Теперь остается только обратиться к функции drawPoints. Обращение выполняется в небольшой функции reposition. Она изменяет переменную rotation в зависимости от положения курсора в правой или левой части экрана. Функция также задает переменную plane исходя из положения курсора по вертикали. Затем функция вызывает функцию drawPoints для задания текущей позиции каждой точки.
// Изменяем позицию куба в каждом кадре,
function reposition () {
rotation += (275-_xmouse)/1000;
plane =- (200-_ymouse)/100;
drawPoints();
}
Функция reposition вызывается в каждом кадре из клипа, который находится за пределами рабочего поля и предназначен для запуска данной части кода при каждом его повторе.
onClipEvent(enterFrame) {
_root.reposition ( );
}
Создание ролика практически завершено. Восемь точек на экране составляют куб, который вращается и поворачивается в зависимости от того, как пользователь перемешает мышь. Ролик можно посмотреть в 3dcubepoints.fla. Фрагмент этой анимации. изображен на рис. 5.10.

Рисунок 5.10 Трехмерный куб, представленный восемью точками на экран
Увеличение кнопок
Исходный файл: Expandingbuttons.fla
Многие сайты используют Flash для навигации от страницы к странице. Даже простой Flash-ролик с одной кнопкой может значительно оживить статическую Web-страницу. При помощи ActionScript вы сможете сделал эти кнопки анимированными.
к ним курсор мыши, не
Задача проекта - создать кнопки, которые в случае, если подвести к ним курсор мыши, не меняют цвет, а увеличиваются и затем, когда курсор убран, возвращаются к нормальному размеру. На рис. 5.1 изображенс пять подобных кнопок, курсор расположен над второй из них.

Рисунок 5.1 Если поместить курсор мыши над кнопкой, она увеличивается
Взглянув на рисунок, можно подумать, что когда на кнопку наводится курсор, она изменяет свой размер внезапно. Однако увеличение кнопки происходит не в одно мгновение, а постепенно, создавая приятный визуальный эффект. Посмотреть, как это выглядит, можно загрузив ролик Expandingbuttons.fla .
Задача этого проекта - создать ролик, который будет изображать вращающуюся спираль с постепенно меняющимися цветами. При этом вы изучите, как функционируют объект Color и свойство клипа _rotation.
Задача данного раздела - научиться использовать случайные числа для создания визуальных эффектов. Возможно, вы захотите создать "эффект старого кино", когда на изображении кое-где появляются царапины и точки.
Аналоговые часы
Исходный файл: Simpleclock.fla, Betterclock.fla
Одной из возможностей использования ActionScnpt является ние даты и текущего времени на компьютере пользователя. Это осуществляется благодаря объекту Date. Этот объект может использоваться различными способами, простейшим из них является создание анимированных аналоговых часов.
Другие возможности
Вы можете внести изменения в код списка ответов. Совсем необязательно придерживаться используемой в нашем примере модели "да/ нет/не знаю". Ваши вопросы и ответы могут касаться определенной темы, например, выиграет ли сегодня местная спортивная команда или какой будет погода.
Сценарий, рассматриваемый в данном разделе, выполняется независимо дизайна музыкального автомата. Ваше устройство может быть похоже на напольный музыкальный автомат или совсем не походить на него. Вы даже можете создать музыкальный автомат с многочисленными экранами, представляющими различные группы песен. Кнопки "Forward" (Вперед) и "Back" (Назад) используются для перехода от кадра одной песни к кадру другой песни.
В качестве стрелок часов вы можете использовать любой объект. Это могут быть простые линии или созданное вами изображение. Вы также можете украсить часы числами или фоновыми рисунками.
Еще одной интересной возможностью будет создание часов, стрелки которых двигаются в обратном направлении. Такие часы можно иногда встретить в магазинах и ресторанах. Вы также можете добавить звук, который будет воспроизводиться каждый час или каждые 15 минут.
Изображение стекла было создано аналогично пузырькам. Благодаря применению свойства альфа-прозрачности сквозь него видны пузырьки Для того чтобы ролик вписывался в ваш сайт или проект, вы можете украсить его своим логотипом.
Дополнительно вы можете добавить в игру кнопки для загрузки каких-то уже существующих колоний. Это избавит вас от необходимости каждый раз создавать их заново.
Игра "Жизнь"
Исходный файл: gameoflife.fla
Игра "Жизнь" известна как результат серьезных разработок в области искусственного интеллекта и одновременно как популярная игра. Она была изобретена математиком Джоном Конвэйем и приобрела известность благодаря опубликованной в 1970 году статье в журнале "Scientific American". Вскоре после этого игра стала чрезвычайно популярной среди программистов.
Выглядит все очень просто — в ячейки сетки на игровом поле помещается произвольный набор точек. На очередном шаге игры содержание каждой ячейки сетки подвергается преобразованиям согласно определенному набору правил. Если данная ячейка содержит точку и в прилегающих к ней ячейках находится две или три точки, то содержимое данной ячейки остается без изменений. Если в прилегающих ячейках содержится меньше двух точек, то точка в данной ячейке "умирает" от одиночества, а если больше трех, то точка "умирает" от тесноты. Если же данная ячейка пуста и в прилегающих ячейках содержится ровно три точки, то в данной ячейке "рождается" новая точка.
Вот и все правила, которые вам нужны. Результаты могут оказаться удивительными. Попробуйте запустить исходный файл. Создайте колонию точек подобно изображенным на рис. 6.15 и нажмите кнопку Run.
Использование объекта Date
Объект Date можно представить как небольшой массив, содержащий некоторую информацию о текущем моменте времени. При создании объекта Date за основу берется текущее время, установленное на компьютере пользователя.
Не стоит полагаться на точность времени, установленного на компьютере пользователя. Вы удивитесь тому, сколько людей имеют неточные часы. Тем не менее я обычно не задумываясь использую эти часы, особенно для игр. Если неправильно указано время отправки электронного письма, это может привести к проблемам, для flash-ролика точность времени не так важна.
Объект Date включает следующие элементы: число, месяц, год, часы, минуты и секунды. Для вывода любого из них необходимо использовать соответствуюшую функцию: getDate (). Приводимая ниже программа обработки содержит все функции, которые используются для получения информации из объекта Date:
on (release) {
now = new Date();
trace("toString:" + now.toString());
trace("getDate:" + now.getDate());
trace("getDay:" + now.getDay());
trace("getFullYear:" + now.getFullYear());
trace("getHours:" + now.getHours());
trace("getMilliseconds:" + now.getMilliseconds());
trace("getMinutes:" + now.getMinutes());
trace("getMonth:" + now.getMonth());
trace(getSeconds:" + now.getSeconds());
trace("getTime:" + now.getTime());
trace("getTimezoneOffset:" + now.getTimezoneOffset ());
trace("getYear:" + now.getYear());
trace("getUTCDate:" + now.getUTCDate());
trace("getUTCDay:" + now.getUTCDay());
trace("getUTCFullYear:" + now.getUTCFullYear());
trace("getUTCHours:" + now.getUTCHoursO);
trace("getUTCMilliseconds:" + now.getUTCMilliseconds());
trace("getUTCMinutes:" + now.getUTCMinutes());
trace("getUTCMonth:" + now.getUTCMonth());
trace("getUTCSeconds:" + now.getUTCSeconds());
Следует обратить внимание на несколько моментов. Все функции UTC подразумевают, что система пользователя настроена на соответствующую временную зону. Для того чтобы получить всеобщее (по Гринвичу) время, необходимо добавить или вычесть определенное количество часов. Результатом выполнения функции getTime будет количество миллисекунд с 1 января 1970 года. Функция day обозначает день недели и задается числом от 0 до 6. Месяц представляет собой число от 0 до 11. Число выбирается из диапазона от 1 до 31. Возможно, все это трудно для понимания и запоминания, однако данные функции аналогичным образом задаются и в других языках программирования, например С и JavaScript.
Вот результат выполнения всех функций trace:
toString:Sat Oct 14 18:47:06 GMT-0600 2000
getDate:14
getDay:6
getFullYear:2000
getHours:18
getMilliseconds:0
getMinutes:44
getMonth:9
getSeconds:7 getTime:971570647000
getTimezoneOffset: 360
getYear:100
getUTCDate:15
getUTCDay:0
getUTCFullYear:2000
getUTCHours:0
getUTCMilliseconds:0
getUTCMinutes:44
getUTCMonth:9
getUTCSeconds:7
Вы можете задать любой элемент объекта Date. Каждая функция, начинаюшаяся с get, имеет соответствующую ей функцию, начинающуюся с set. К примеру, для установки часа используется функция setHour (newHour) Имейте в виду, что это приведет к изменению только объекта Date, которому вы обратились, а не системных часов пользователя. При создании нового объекта Date время в нем будет установлено в соответствии системными часами.
К сведению
Кроме рассмотренных функций в сценарии кадра имеется код, вызывающий функцию creatGrid, и команда stop (). Возможна также другая реализация. Дело в том, что игра нуждается в получении определенных данных для запуска. Ведь если вы нажмете кнопку Run при пустом игровом поле, то ничего не произойдет. Поиграйте с колонией, изображенной на рис 6.15. Ее называют "маленький взрыв". Программисты, впервые реализовавшие игру "Жизнь", придумали имена некоторым таким "цивилизациям".
Попробуйте создать свои колонии или поищите в Интернете уже существующие. Поиск по ключу "game of life" откроет вам множество страниц с самыми разнообразными конфигурациями.
В конце анимации вы можете поместить команду stop (), чтобы воспроизведение ролика не повторялось, а также другую кнопку, которая ocyществит возврат ролика к кадру 1 в случае, если пользователь захочет задать еще один вопрос.
Лавовая лампа
Исходный файл: Lavalamp.fla
Этот ролик воссоздает классическую лавовую лампу. На компьютерах и в сети можно увидеть множество подобных объектов. Многие из них представляют собой простые Flash-анимации, создаваемые без написания кода.
Но в этом случае после окончания анимации узор повторяется, а интереснее сделать такую лавовую лампу, узор которой в каждый момент был бы разным.
Подготовка ролика
После того как вы поместили 10 экземпляров клипа на рабочее поле и присвоите песням имена в первом кадре главной временной шкалы, осталось добавить звук.
Прежде всего, импортируем 10 песен в библиотеку ролика и присвоим им имена, начиная с "song1" и заканчивая "song10". После импорта каждого звукового файла необходимо изменить его свойство связи таким образом, чтобы он был включен в создаваемый .swf-файл. Для каждой песни требуется создать идентификатор и поставить флажок напротив свойства Export for ActionScript. Соответствующее диалоговое окно показано на рис. 6.8. Его можно вызвать из меню Options окна Library.

Рисунок 6.8 Диалоговое окно Symbol Linkage Properties позволяет включать звуки в swf-файл, даже если их нет в главной временной шкале
К сожалению, во Rash нет возможности использования внешних звуковых файлов. Единственным способом создать подобный музыкальный автомат будет импорт всех песен и включение их в swf-файл. Будем надеяться, что в следующих версиях программы появится возможность доступа к внешним звуковым файлам и их воспроизведения
При помоши объекта Date можно создать интересные часы. Переводя значения часов, минут и секунд текущего времени в градусы, вы можете задать параметр „rotation трех различных клипов таким образом, чтобы они двигались, как стрелки часов.
На рис. 6.10 показан внешний вид таких часов. Короткая рука обозначает часовую, длинная - минутную, а хвост - секундную стрелки.

Рисунок 6.10 Часы показывают 1 час 45 минут и 10 секунд
На рисунке не видно, что руки (и хвост) часов двигаются подобно стрелкам настоящих часов. Эти действия выполняются в три этапа. Вначале полученное значение текущего времени помешается в переменные hour, minute и second. Затем значения этих переменных преобразуются в значения углов. Далее полученные значения используются для задания параметра _rotation трех клипов, представляющих руки и хвост.
Создание ролика Lava Lamp требует особой тщательности. Например, пузырьки представляют собой круги без границы и с радиальной заливкой между непрозрачным и прозрачным красным цветом. Прозрачный красный цвет получается в результате установки свойства alpha в значение 0%. На рис. 6.14 изображен клип, а также панели Fill (Заливка) и Mixer (Миксер), при помощи которых можно задать градиент красного цвета.

Рисунок 6.14 В панели Fill можно задать градиентную заливку цветом. Панель Mixer позволяет задавать значение прозрачности
Сначала рассмотрим, как выполняется анимация. Ролик состоит из двух частей. Первая представляет собой статический кадр, который выглядит, как показано на рис. 6.1. Ролик будет запущен после щелчка по хрустальному шару.
Единственным необходимым элементом в этом ролике является команда stopO, помещаемая в любой слой. На рис. 6.2. показана главная временная шкала ролика. Строчная буква "а" в первом кадре второго слоя (слоя "Text") обозначает, что этому кадру назначен код ActionScript, в данном случае команда stop ().

Рисунок 6.2 Главная временная шкала содержит полную анимацию хрустального шара
Устройство главной временной шкалы зависит от фантазии аниматора. В рассматриваемом примере изображение лисы состоит из основного слоя и одного слоя для каждой руки. Изображение шара также включает несколько слоев.
Особое внимание следует обратить на то, как анимация развертывается во времени. Первый кадр представляет собой статический кадр без анимации, он содержит текст (см. рис./6.1) и невидимую кнопку, которая помешается поверх хрустального шара.
Кнопка создается следующим образом: создайте новую кнопку, при помощи любой цветной области (например, зеленого прямоугольника) придайте ей нужную форму и поместите в один из верхних слоев главной временной шкалы. На данном этапе кнопка будет видна (рис. 6.3).

Рисунок 6.3 В первом кадре ролика видно изображение кнопки над хрустальным шаром
Нам необходимо, чтобы кнопка была активной и в тоже время скрытой от пользователя. Для этого в панели Properties выберите эффект Alpa и установите значение прозрачности 0% (рис. 6.4). Можно просто заполнить в кнопке только кадр Hit, тогда она также будет не видна пользователю, но активна.

Рисунок 6.4 В панели Properties можно установить значение параметра Alpha в 0%, тем самым делая элемент невидимы
Эффект Alpha назван по аналогии с термином "alpha channel" (альфа-канал), который используется для описания изображений. Считается, что графическое изображение состоит из четырех каналов: красного, зеленого, синего и альфа. Первые три канала определяют цвет пикселов, последний - их прозрачность. Если значение альфа-канала равно 0, изображение совершенно прозрачно. Поэтому при установке свойства Alpha в значение 0 flash-элемент станет невидимым.
Подготовка ролика В дополнение
Функция cycle является центральным моментом нашей программы. Она используется для вычисления правил применительно к каждой ячеке. Обратите внимание, что мы дублируем массив grid. Это делается для того, чтобы при изменении значения какого-нибудь элемента массива grid это не повлияло на дальнейшие вычисления на данном шаге программы. Все вычисления происходят опираясь на значения элементов массива baseGrid.
function cycle() {
// Дублируем массив grid. var baseGrid = duplicateGrid();
// Делаем проход по всем ячейкам,
for(y=0;y
for(x=0;x
thisBox = baseGrid[y][x];
mc = this["gridbox "+x+" "+y];
// Вычисляем количество "заселенных" ячеек вокруг
// данной.
n = 0;
n += baseGrid[y-1][x-1];
n += baseGrid[y-1][x];
n += baseGrid[y-1][x+1];
n += baseGrid[y][x-1];
n += baseGrid[y][x+1];
n += baseGrid[y+1][x-1];
n += baseGrid[y+1][x];
n += baseGrid[y+1][x+1];
// Если в этой ячейке уже была точка и если количество
// "жильцов" вокруг равно 2 или 3, то точка остается, .
if (thisBox) {
if ((n == 2) or (n == 3)) {
newValue = true;
} else {
newValue = false;
}
// Новая точка "рождается", если ячейка была пуста
//и если в смежных ячейках находится ровно 3 точки.
} else {
if (n == 3) {
newValue = true;
} else {
newValue = false;
}
}
// Меняем текущий кадр клипа mc.
grid[y][x] = newValue;
if (newValue) {
mc.gotoAndStop(2);
} else {
mc.gotoAndStop(1);
}
}
}
}
Функция duplicateGrid() создает копию массива grid и возвращает ее в качестве своего значения.
function duplicateGrid() {
var newGrid = new Array();
for(y=0;y
var temp = new Array();
for(x=0;x
temp.push(grid[y][x]);
}
newGrid.push(temp);
}
return(newGrid);
}
Да, но почему мы должны пользоваться функцией duplicateGrid(), вместо того чтобы просто приравнять массив baseGrid массиву grid? Потому что иначе у нас не было бы реальной копии массива. Вместо этого и grid и baseGrid ссылались бы на один и тоже массив и изменения в массиве grid появлялись бы и в массиве baseGrid.
Клип "actions" содержит обработчик onClipEvent (enterFrame), который вызывает функцию runCicle при каждом обращении к кадру. Эта функция проверяет глобальную переменную running и запускает сусle, если ее значение истинно (true).
function runCycle() {
if (running) {
cycle();
}
}
Рассмотрим теперь сценарии кнопок. Каждая кнопка содержит обработчик вида on (release), который вызывает одну из следующих функций. Первая (кнопка Run) задает глобальной переменной running значение true.
function startCycle() {
running = true;
}
Если же пользователь нажмет кнопку Step, то функция cycle будет вызвана лишь один раз и переменная running не изменит своего значения.
function stepCycle() {
cycle();
}
При нажатии кнопки Stop переменной running присваивается значение false.
function stopCycle() {
running = false;
}
И наконец, нажатие кнопки Clear очищает массив grid и все ячейки сетки
function clear() {
for(y=0;y
for(x=0;x
grid[y][x] = 0;
this["gridbox "+x+" "+y].gotoAndStop(1);
}
}
running = false;
}
Осталось только рассмотреть код, который находится на кнопке внутри каждого клипа-ячейки. Этот сценарий определяет состояние ячейки. В функции creatGrid мы определили переменные х и у для каждого клипа. Это позволяет установить соответствие между ячейками и элементами массива и вносить изменения в массив при изменении состояния ячейки.
on (release) {
if (_currentframe == 1) {
gotoAndStop(2);
_parent.grid[y][x] = true;
} else {
gotoAndStop(l);
_parent.grid[y][x] = false;
}
}
Подход
Прежде чем создавать часы, необходимо научиться работать с объектом Date. Именно он содержит текущее время, доступное для отображения
Для создания лавовой лампы, работающей по принципу случайности (рис. 6.13), необходимо использовать ActionScript. Вначале необходимо создать 20 клипов, представляющих пузырьки лавовой лампы. Затем надо задать постоянный вызов функции, перемещающей пузырьки вверх и вниз по экрану.

Рисунок 6.13 Объект "лавовая лампа " состоит из дна, крышки, внутренней части из прозрачного стекла и красных пузырьков
Ролик начинается с создания сетки, состоящей из клипов (ячеек). Также создается двумерный массив булевых переменных. Каждый элемент массива соответствует определенной ячейке и указывает, в каком кадре находится этот клип-ячейка ( то есть находится ли в данной ячейке "жилец").
Основная функция ролика просматривает все ячейки и вычисляет изменения в них. Выполнение этой функции представляет собой один шаг игры. Если пользователь нажимает кнопку Run, ролик выполняет эти шаги непрерывно. При выборе кнопки Step исполняется только один шаг.
Наиболее сложной задачей в данном ролике является создание изображений и анимации. Сценарий же довольно прост.
Создание подобного ролика, содержащего 10 различных кнопок, с 10 различными кодами, предназначенными для воспроизведения 10 различных песен, является интересной задачей. Ролик будет работать, однако его сложно создать и еше сложнее изменить.
Наиболее простым способом будет создать одну кнопку и использовать ее 10 раз, один раз для каждой песни. Каждая кнопка будет представлять собой клип, содержащий одну и ту же кнопку. Таким образом, в библиотеке ролика окажется всего один клип и одна кнопка. Этот клип будет помешен на рабочее поле 10 раз, все его копии будут идентичны. Первое действие при запуске ролика - изменение текста каждой копии клипа. Это действие описывается при помощи следующего кода:
// Задаем названия песен.
this["1"].text = "Song Name 1";
this["2"].text = "Song Name 2";
this["3"].text = "Song Name 3";
this["4"].text = "Song Name 4";
this["5"].text = "Song Name 5";
this["6"].text = "Song Name 6";
this["7"].text = "Song Name 7";
this["8"].text = "Song Name 8";
this["9"].text = "Song Name 9";
this["10"].text = "Song Name 10";
Для того чтобы упростить задачу, клипам присвоены имена от " 1" до "10". В результате выполнения вышеприведенного кода все копии клипа будут отображать разные названия песен. Поэтому, несмотря на то, что в библиотеке содержится один клип, все его копии будут выглядеть по-разному.
Более того, названия всех 10 песен будут включены в один сценарий Если бы каждый клип содержал, название одной песни, вам пришлось бы проделать немало работы, открывая и закрывая каждый из 10 клипов для внесения в него изменений. Данный сценарий дает возможность быстро изменить все названия песен.
Свести количество клипов к одному помогает и код, назначенный кнопке внутри клипа:
on (release) {
_root.playSong (this._name);
}
Эта строка кода отправляет одно из имен клипа от "1" до "10" в функцию playSong, находящуюся на корневом уровне (уровне рабочего поля). Эта часть кода может выполняться в любом клипе, так как в каждом случае использует различное имя экземпляра клипа. Если при создании нового экземпляра клипа вы не забыли назначить ему новое имя, значение переменной this._name будет каждый раз иным.
Данный код позволяет использовать одну копию клипа необходимое число раз. В случае внесения в клип каких-либо графических или функциональных изменений вам придется сделать это всего единожды. Кроме того, конечный .swf-файл будет меньше файла, библиотека которого содержит 10 копий аналогичных клипов.
Создание кода
В сущности «волшебство» данного ролика создается в сценарии Action Script кнопки. Как было сказано выше, сценарий задает переход ролика ко второму кадру и запускает анимацию. Это фактически последнее важное событие. Перед этим генерируется ответ, который помешается в текстовую область.
Так как ответ активизируется щелчком по кнопке, весь код необходимо поместить в сценарий, назначенный кнопке. Такой сценарий всегда начинается с оператора on, далее следует описание реакции на событие. Одним из часто используемых событий является событие release (нажатие кнопки).
Вначале сценарий создает массив и заполняет его списком ответов. Для этого существует множество способов. Один из них приведен ниже:
responses = new Array("Yes", "No", "Ask again later","It is certain", "Doubtful", "Probably", "The answer is unclear","Of course not!", "Certainly!", "It looks positive", "It looks negative");
Это наиболее короткий способ создания массива и его одновременного заполнения. Однако он выглядит немного беспорядочно, так как текст переносится с одной строки на другую. Приведем другой способ:
responses = new Array();
responses[0]("Yes");
responses[1]("No");
responses[2]("Ask again later");
responses[3]("It is certain");
responses[4]("Doubtful");
responses[5]("Probably");
responses[6]("The answer is unclear");
responses[7]("Of course not!");
responses[8]("Certainly!");
responses[9]("It looks positive");
responses[10]("It looks negative");
Этот способ является более аккуратным, в нем каждый ответ располагается на отдельной строке. Вы можете сразу увидеть, из каких элементов он состоит. Однако здесь вам придется в каждой строке вводить номер элемента в скобках. В случае ошибки вы можете пропустить очередной ответ или оставить место пустым. Поэтому лучше пользоваться третьим способом:
Код, задающий воспроизведение звукового файла, несложный, но и не такой простой, как можно было бы ожидать. Вместо одной команды воспроизведения звука вам придется записать три строки: первая создает звуковой объект, вторая соотносит звуковой файл из библиотеки объектом, третья задает воспроизведение звукового файла.
song = new Sound();
song.attachSound("song1") ;
song.start();
Функция playSong должна выполнять еще несколько действий. Прежде всего, останавливать воспроизведение предыдущей песни. Это осуществляется при помощи команды stop. Предположим, что предыдущая песня содержится в глобальной переменной song и воспроизводится в данный момент. Приведем простой вариант функции:
function playSong(songnum){
// Останавливаем воспроизведение предыдущей песни,
song.stop();
// Проигрываем новую песню,
song = new Sound ();
song.attachSoundt "song"+songnum);
song.start();
}
Осталось добавить еще один специальный эффект - подсвечивание названия выбранной песни. Клип каждого выбираемого элемента содержит два кадра: без подсветки и с подсветкой. На рис. 6.9 изображение музыкальный автомат с подсветкой выбранного элемента.
Перед запуском воспроизведения каждой песни необходимо y6eдиться в том, что подсветка всех песен выключена, а затем включить подсветку только выбранной песни:
function playSong(songnum) {
// Останавливаем воспроизведение предыдущей песни.
song.stop();
// Убираем подсветку.
for(i=1;i
this[i].gotoAndStop(1);
}
// Проигрываем новую песню,
song = new Sound();
song.attachSound("song"+songnum);
song.start();
this[songnum].gotoAndStop(2);
}

Рисунок 6.9 Музыкальный автомат воспроизводит песню под номером 2
Код, который выполняет все вышеописанные действия, - это cценарий onClipEvent (enterFrame), помещаемый в клип. Код можно посмотреть в файле Simpleclock.fla.
onClipEvent (enterFrame) {
// Узнаем текущее время.
now = new Date();
hour = now.getHours();
minute = now.getMinutes();
second = now.getSeconds();
// Конвертируем в значение для 12-часового дня.
if (hour > 12) {
hour -= 12;
}
// Рассчитываем углы для поворота стрелок.
hourAngle = 360*hour/12;
minuteAngle = 360*minute/60
secondAngle = 360*second/60;
/// Поворачиваем сами ролики
_root["hour hand"]._rotation = hourAngle;
_root["minute hand"]._rotation = minuteAngle;
_root["second hand"]._rotation = secondAngle;
}
Чтобы определить значение углов, значение времени делится на наибольшее возможное значение и умножается на 360. Например, значение минут делится на 60, в результате чего получается значение между 0 и 1, а затем умножается на 360, что дает значение угла между 0° и 360°. Чтобы стрелка была 12-, а не 24-часовой, из значения часов вычитается 12.
Результатом каждой операции является угол от 0° до 360°. 0° обозначает 0 (или 12) часов, 0 минут, 0 секунд. В данном случае изображения всех трех клипов, представляющих стрелки часов, будут указывать вверх (рис. 6.11). Затем, после задания параметра „rotation, стрелки будут указывать на соответствующее место.

Рисунок 6.11 Руки и хвост (то есть стрелки часов), направленные четко вверх, соответствуют 12:00:00. Когда вы зададите параметр _rotation, стрелки будут указывать в соответствующем направлении
Проблема состоит в том, что устройство будет работать не совсем как обычные часы. Например, на рис. 6.10 часовая стрелка указывает на 9 часов. Она будет продолжать указывать на отметку 9, даже когда будет 9:59, а затем в 10:00 сразу передвинется на отметку 10. В настоящих часах часовая стрелка будет в течение часа постепенно передвигаться, пока не достигнет отметки 10 в 10 часов. Для того чтобы получить такой результат, необходимо немного увеличивать угол часовой стрелки каждую минуту и угол минутной стрелки каждую секунду, Приведем соответствующий код:
Lava Lamp использует 20 экземпляров клипа, созданных из одного библиотечного эталона. С помощью команды attachMovie копии клипа добавляются в ролик. Более подробно о команде attachMovie рассказано в главе 5, раздел "Эффект трехмерности".
При запуске ролика в первом и единственном кадре временной шкалы выполняется функция initLamp. При этом помимо 20 клипов пузырьков будет создан массив объектов, которые определяют скорость движения каждого пузырька.
Кроме того, верхняя и нижняя части лампы будут непрозрачными, из-за чего здесь пузырьки не будут видны. Поверх клипов пузырьков будет помешено изображение полупрозрачного стекла.
При использовании команд attachMovie или duplicateMovieClip необходимо указать уровень нового клипа. Уровень определяет порядок перекрывания клипов. Все новые клипы будут помешены перед существующими. Это значит, что пузырьки будут располагаться перед изображениями верхней, нижней и прозрачной частей лавовой лампы. С помощью команды duplicateMovieClip вы можете создать новые копии этих трех изображений, которые будут помешены поверх пузырьков.
Приведем код функции initLamp:
function initLamp () {
// Инициализируем переменные, обозначающие верхнюю и нижнюю
// координаты лавовой лампы по оси Y.
top = 0;
bottom = 300;
// Создаем экземпляры клипа, содержащего пузырек.
numBubbles = 20;
for (i=0; i
attachMovie("bubble", "Bubble"+i, i);
}
// Дублируем изображения стекла, низа и верха лампы, чтобы // они оказались над пузырьками.
duplicateMovieClip("Glass", "Glass", i + +);
duplicateMovieClip("Top", "Top", i++);
duplicateMovieClip("Bottom", "Bottom", i++);
// Создаем объекты, содержащие значение скорости пузырьков.
bubbles = new Array();
for (i=0; i
bubbles[i] = {speed:0};
}
}
После того как все элементы подготовлены, воспроизведение ролика осуществляется по следующему принципу: время от времени вызывается функция, которая обновляет местоположение пузырьков и создает новые. Клип, расположенный за пределами рабочего поля, вызывает функцию moveBubbles в каждом событии enter Frame.
Функция moveBubbles задает перемещение пузырьков вверх или вниз и их остановку в верхней или нижней части ролика, а также в одном случае из 30 вызывает функцию newBubble для создания нового пузырька.
Волшебный хрустальный шар
Исходный файл:
Crystalball.fla
Наверное, самой распространенной интерактивной программой, которую можно встретить в Internet, является программа-предсказатель, работаюшая на основе случайных чисел. Обычно она называется "Маеgic Eight Balls" (Восемь волшебных шаров), по имени популярной игрушки Tyco.
На рис. 6.1 показано, как может выглядеть подобная игра.

Рисунок 6.1 Лиса ответит на ваш вопрос : после того, как вы щелкните по хрустальному шар
После щелчка по шару лиса
После щелчка по шару лиса помашет лапами и пользователь получит ответ, который будет выбран наугад из списка.
Создание музыкального автомата - наглядный способ продемонстрировать, как используется звук во Flash. Это обычный ролик, воспроизводящий несколько песен.
Интерфейс программы изображен на рис. 6.7. Такой музыкальный автомат может содержать до 10 различных песен. Песня воспроизводится после щелчка по ее названию в списке.

Рисунок 6.7 Виртуальный музыкальный автомат напоминает устройство, которое можно было встретить в 50-е годы в любой закусочной
В данном разделе мы создадим лавовую лампу, функционирующую по принципу случайности. Это значит, что код случайным образом определяет, когда и где появляются новые пузырьки. В результате узор никогда не будет повторяться.
Время, запрограммированное в компьютере пользователя, должно отображаться в виде настенных или наручных часов. Часы должны иметь часовую, минутную и секундную стрелки. Лучше сделать часы необычными и в качестве стрелок использовать не простые линии, а какой-нибудь клип.
Программа создает сетку, заполняющую экран. Каждая ячейка может содержать или не содержать точку. Щелкнув по ячейке, пользователь может изменить ее состояние.

Рисунок 6.15 В игре "Жизнь" живут и умирают маленькие красные точки
Когда пользователь завершает наполнение ячеек, он нажимает кнопку начала игры. При каждом проигрывании кадра применяется к каждой ячейке описанный набор правил. В результате наполнение некоторых ячеек меняется.
Пользователь может нажать кнопку Stop для остановки игры. Имеются также кнопка пошагового исполнения алгоритма (Step) и кнопка очистки игрового поля (Clear).
Альбом для рисования
Исходный файл: Drawing-line.fla, Drawing-fill.fla
Хотя предыдущие два примера используют ваши творческие способности, в действительности они не дают возможности создавать что-либо новое. Теперь давайте рассмотрим программу для рисования, работа в которой начинается с чистого листа и которая позволяет пользователю изображать все, что угодно, и распечатывать результат.
Добавление кнопок Clear и Print
Чтобы очистить рабочую область, мы просто нарисуем сверху заполненный цветом области прямоугольник. Это выполняется с помощью сценария кнопки Clear (Очистить).
Мы устанавливаем толщину линии 0. Затем перемещаем указатель в верхний левый угол нашей области и рисуем прямоугольник, который точно ее повторяет и определяет область заливки. Цвет заливки - белый, так как именно он выбран фоновым в нашем ролике.
on (release) {
// Толщина линии - ноль.
_roou.lineStyle(0,OxFFFFFF,100);
// Перемещаем указатель в верхний левый угол.
_root.moveTo(actions.xmin,act ions.ymin);
// Создаем область заливки.
_root.beginFill(OxFFFFFF);
_root.lineTo(actions.xmax,actions.ymin);
_root.lineTo(actions.xmax,actions.ymax);
_root.lineTo(actions.xmin,actions.ymax);
_root.lineTo(actions.xmin,actions.ymin);
_root.endFill();
}
Еше легче создать кнопку Print (Печать). Для этого необходимо добавить команду print. Осталось еше присвоить метку "#р" единственному кадру ролика.
on (release) {
// Распечатываем клип
print(_root,"bframe");
}
Команда print выводит заданный клип на печать. Добавив к команде слева _root, вы можете напечатать все содержимое рабочего поля. Второй параметр определяет границы области печати. Подробности вы найдете в руководстве пользователя Flash.

Рисунок 7.7 Изображение примера использования ролика.
Другие возможности
Подобная программа может применяться почти к любому объекту. Таким объектом, например, может быть машина, в которой пользователь может изменять колеса и другие детали, или лицо с различными вариантами глаз, носа, ушей, волос и т. д.
Вы можете усовершенствовать программу, добавив возможность выбора толщины линии по аналогии с цветами. Можно создать кнопку, которая будет определять переменную lineSize в клипе "actions". Добавив в палитру белый цвет, вы дадите пользователю возможность стирать уже нарисованное.
Вы можете легко заменить имеющиеся звуки любыми другими. Просто удалите старые звуки из библиотеки и импортируйте на их место ваши собственные. Не забудьте произвести настройку диалогового окна Symbol Linkage Properties.
Вы также имеете возможность изменять количество звуков, например, уменьшать количество циклов барабанного боя и увеличивать количество отдельных звуков. Звуков может быть сколько угодно, главное, чтобы имена копий клипов совпадали с именами соответствующих звуков библиотеки.
Ничто не мешает вам изменить анимацию любого переключателя, Обладая достаточным количеством времени, вы можете отказаться от идеи повторно используемых клипов и создать свой клип для каждого переключателя. Но имейте в виду, что это усложнит вашу задачу, если вы захотите потом как-то еще изменить ролик.
В файле примера лиса, выполнив один раз выбранное пользователем движение, возвращается к основному танцу. Вы можете изменить программу таким образом, чтобы лиса повторяла выбранное движение до тех пор, пока пользователь не выберет новое. Этого можно достичь возвращением каждой последовательности кадров, отвечающей за определенное движение, к своей собственной метке вместо "danceO". В таком случае вам может понадобиться отдельная кнопка в кадре "record" для возвращения лисы к ее основному танцу.
К сведению
He забудьте присвоить каждой из 18 кнопок уникальное имя и сопоставить это имя с именем соответствующего звука в библиотеке. Кроме того,название звука необходимо задать в диалоговом окне Symbol Linkage Properties (рис. 7.9).
То, какой будет анимация каждого типа кнопки, решаете вы. В нашем примере кнопки барабанного боя мигают, изменяя свой цвет с белого на черный и обратно, кнопки басов и отдельных звуков увеличиваются. Чтобы обеспечить непрерывное воспроизведение, в последний кадр циклов барабанного боя и басов необходимо вставить команду gotoAndPlay (2). Клипы отдельных звуков после окончания своего воспроизведения должны возвращаться к кадру 1. Первый кадр этих звуков должен содержать команду stop О для того, чтобы их воспроизведение запускалось при первой загрузке ролика.
Три кнопки в кадре "record", инициирующие танец, должны содержать сценарии для вызова функции danceButton. Вот пример для одной из кнопок:
on (press) {
danceButton("dance1");
}
В кнопке Done должен содержаться сценарий для вызова функции stopRecord.
on (press) {
stopRecord();
}
Клип "actions" в кадре "playback" содержит код, вызывающий функцию danceFrame при каждом обращении к этому кадру.
onClipEvent(enterFrame) {
_root.danceFrame();
}
Следует также назначить команду gotoAndstop каждой из кнопок главного меню. В первый кадр главной временной шкалы поместите команду stop(), чтобы остановить анимацию в начальный момент времени.
Для того чтобы закончить создание ролика Makeafox-switch.fla, следует обратить внимание еще на несколько деталей. Во-первых, каждый первый кадр клипа должен содержать команду stop(). Это поможет избежать безостановочного воспроизведения всех вариантов клипа при первом запуске ролика. Затем каждый клип должен быть помещен на рабочее поле и назван, как соответствующий элемент списка в коде.
Не забудьте поместить команду stop() в первый кадр клипа, содержащего кнопку, включающую режим заливки. Вы можете создать намного больше кнопок для предоставления пользователю большого количества цветов для рисования.
Музыкальный миксер
Исходный файл: Musicmixer.fla
Flash позволяет работать не только с графическими объектами. Вы, например, можете воспроизводить одновременно несколько звуков, создавая музыкальный коктейль. При этом пользователь получит право выбирать любой музыкальный отрезок и время его воспроизведения.
Подготовка ролика
Для создания игрушки-конструктора, работающей по методу drag-and-drop, прежде всего необходимо иметь различные графические изображения. На рис. 7.1 в правой части изображено туловище, в левой - различные изображения рук, ног, ртов и глаз.

Рисунок 7.1 Изображенные слева части тела можно переместить к расположенному справа туловищу
Ролик можно запустить, открыв файл Makeafox-drag.fla. Вы можете выбрать любую часть тела и переместить ее в любую часть экрана.
Основными элементами ролика являются 18 звуков. В примере MUSICmixer.fla использовались звуки, созданные профессиональным композитором. Вам придется сочинить звуки самому, привлечь к этому друга или коллегу или позаимствовать музыку из любых других источников.
Циклы барабанного боя и басов состоят из коротких звуков, создающих законченные музыкальные фразы. Они должны быть короткими, чтобы не перегружать файл, но достаточными для того, чтобы создать интересный звук.
После импорта 18 звуков во Flash в диалоговом окне Symbol Linkage Properties (рис. 7.9) необходимо установить свойство Export for ActionScript, а также задать идентификатор.

Рисунок 7.9 Настройки диалогового окна Symbol Linkage Properties определяют, каким образом звук будет включен во Flash-ролик
Необходимо создать три различных типа кнопок. В действительности они представляют собой не кнопки, а клипы. Поэтому, чтобы избежать путаницы, мы назовем их "переключателями". Переключатели содержат невидимые кнопки, реагирующие на щелчок мыши. Они состоят как минимум из двух кадров. Первый из них соответствует выключенному состоянию переключателя, остальные - включенному. Так как звуки барабанов и басов представляют собой повторяющиеся циклы, анимация этих двух переключателей воспроизводится непрерывно, пока не будет прекращена повторным щелчком мыши. В отличие от этого анимация переключателя отдельного звука воспроизводится один раз и затем возвращается к состоянию "выключено". Состав анимационных последовательностей вы можете просмотреть в файле Musicmixer.fla.
Кнопки в переключателях - это простые белые фигуры, которые помешаются за другими графическими изображениями, чтобы их не было видно. В примере для переключателей барабанов и басов используется небольшая круглая кнопка, для переключателей отдельных звуков - треугольная. Чтобы было проще размещать кнопки за графическими объектами, создано только два типа изображений кнопок. Шесть копий каждого переключателя помешены на рабочее поле. Их расположение может быть любым (рис. 7.8).
Мы должны сделать клип "dance" правильно. В исходном файле он представляет последовательность из 20 кадров, которая разбита на четыре части по 5 кадров. Каждая часть начинается с кадра, имеющего метку, например "dance0". Последний кадр в каждой последовательности не i держит изображения, но содержит команду gotoAndPlay("dance0") Таким образом, когда данная последовательность движений заканчивается, лиса возвращается к повторению последовательности dance0 (основное движение танца). Остальные три метки кадров называются "dance1", "dance2" и "dance3".
Последний кадр каждой танцевальной последовательности содержит только сценарий. Это сделано потому, что, когда выполняется команда gotoAndPlay (), содержимое кадра не отображается.
Основная временная шкала ролика содержит три кадра. Первый кадр помечен как "menu" (меню) и содержит команду stop(). Второй кадр имеет метку "record"(запись) и третий — "р1ауЬаск" (воспроизведение). Ниже мы рассмотрим код для этих трех кадров.
В кадре "menu" содержится две кнопки: Record и Playback. Я использовал один символ из библиотеки как образец для создания кнопок, но поместил на них различный текст. Каждая из этих кнопок совершает переход на соответствующий кадр.
В кадре "record" содержится четыре кнопки. Три из них включают в танец соответствующее движение, и четвертая прерывает процесс записи.
Наконец, кадр "playback" содержит единственную кнопку, останавливающую воспроизведение.
Подход
Программа должна распознавать нажатие и отпускание кнопки мыши. Она должна определять, над каким клипом находится в данный момент курсор, и предоставлять возможность перетаскивания выбранного клипа при нажатой кнопке мыши.
Это не так легко, как кажется. Для того чтобы определить, какой клип выбрал пользователь, необходимо сравнить позицию курсора мыши с областью, занимаемой каждым клипом.
Библиотека данного ролика имеет не такую, как мы рассматривали раньше, организацию. Вместо отдельных изображений каждого варианта элемента лисы используются клипы. Каждый клип содержит все варианты данного элемента, по одному в кадре. Например, клип "Eyes" ("Глаза") будет стоять из трех кадров, каждый из которых содержит другое изображение глаз.
В приложении используется шесть циклов барабанного боя, шесть циклов басов и шесть отдельных звуковых эффектов. Одновременно может играть только один "барабанный" цикл, поэтому при выборе второго цикла необходимо отменить первый. Басы могут воспроизводиться одновременно. Отдельные звуки воспроизводятся один раз.
В ролике используется три различных набора переключателей. Первый предназначен для выбора цикла барабанного боя. При включении одного из них предыдущий автоматически отключается. Второй набор переключателей используется для одновременного включения одного, нескольких или всех циклов басов. Повторный щелчок по включение кнопке барабанного боя или басов приведет к ее отключению.
Третий набор кнопок предназначен для воспроизведения отдельных звуков. Они включаются только на время воспроизведения звука. В отличие от циклов барабанного боя или басов, которые воспроизводятся непрерывно, повторное воспроизведение отдельного звука можно запустить, только еще раз щелкнув по соответствующей кнопке.
Центральным объектом этой программы является клип "dance". Он содержит всю последовательность танца лисы. Вы можете управлять лисой, перемещаясь к кадру, с которого начинается последовательность, составляющая данное танцевальное па.
Первым делом программа отмечает начало процесса записи. При нажатии кнопки программа фиксирует время нажатия и название движения. Информация помешается в массив объектов следующего формата: {время: значение, движение: значение}.
В начале процесса воспроизведения также отмечается текущее время. Затем программа все время проверяет, не пора ли лисе совершить первое из записанных движений, то, которое является первым элементом массива. Когда этот момент времени проходит, начинается ожидание второго момента времени, и т.д. Специальное танцевальное движение stop используется, чтобы обозначить окончание времени записи. Когда воспроизведение доходит до команды stop, ролик возвращается в главное меню.
Составь лису методом "Перетащи и положи"
Исходный файл: Makeafox-drag.fla
Многие компьютерные игры созданы по подобию игрушек докомпьютерной эры. Одна из таких старых игрушек - "Mister Potato Head" (Господин картофельная голова). Она представляла собой набор пластиковых частей тела которые ребенок мог прикрепить к картошке и сделать смешного человечка. Позже вместо картошки стали использовать пластиковое туловище.
Создание кода
Если вы уже работали во Flash, вы можете подумать, что это легко - необходимо просто использовать клипы частей тела и команды startDrag, и stopDrag. На самом деле такой подход только все усложнит. Я не любитель команды startDrag и не буду использовать ее здесь, поскольку перемешать с ее помощью элементы по рабочему полю не так уж и просто.
Представив каждую часть тела в виде кнопки, вы можете назначить ей обработчик события on (press) и применить команду startDrag. Однако кнопка не может служить в качестве цели команды startDrag, такой целью может быть только клип. Если же вы представите их в виде клипов, им нельзя будет назначить функцию on (press), так как она используется только с кнопками. Еще одним вариантом является представление каждой части тела как клипа с кнопкой внутри. Здесь можно легко запутаться, так как каждый раз при добавлении в ролик новой части вам придется выполнить несколько действий.
Лучшим выходом будет написать код, выполняющий процедуру drag-ard-drop самостоятельно. Отдельным частям не будет назначено никакого кода, благодаря чему их будет легко создавать и добавлять новые.
Весь код поместим в клип "actions", который как обычно находится вне, пределов рабочей области и содержит только надпись "Actions".
Данному клипу назначен сценарий ActionScript, управляющий перемещением всех элементов. Он должен включать несколько функций onClipEvent. Ниже приведено краткое описание событий и реакций на них, которые сценарий должен выполнять:
• load (загрузить) - задание переменной, указывающей, что никакого перемещения еще не происходит;
• mouseDown (кнопка мыши нажата) - определение выбранного элемента и создание переменной, сообщающей, что этот элемент перетаскивается. Определение смешения между местом, над которым нажата кнопка мыши, и центром выбранного элемента;
• mouseUp (кнопка мыши отпущена) - установка начальных параметров переменной, указывающих, что никакой элемент в данный момент не перетаскивается;
• enterFrame (проигрывание кадра) - изменение положения перемещаемого элемента соответственно движению курсора минус разница между координатами центра элемента и координатами точки, по которой щелкнул пользователь.
Здесь не применяется перетаскивание, поэтому сценарий будет немного проще. Код представляет собой сценарий onClipEvent (mouseDown) помешенный в клип "actions", который расположен за пределами рабочего поля клипа. Как и функция hitTest в ролике Makeafox-drag.fla, данный сценарий проверяет, какой клип выбран.
Однако вместо имен "Part1" - "Part 13" клипы получают значащие имена (например, "Eyes" и "Head"). Сценарий должен проверить каждый клип, для чего все клипы собраны в общий список.
При нахождении соответствующего клипа код продвигается на один кадр вперед. Если впереди кадров больше нет, он возвращается к кадру 1.
onClipEvent (mouseDown) {
// Определяем, в каком месте щелкнул пользователь
x = _root._xmouse;
y = _root._ymouse;
// Выясняем, по какому элементу произведен щелчок
list = ["Eyes", "Mouth", "Head", "Legs", "Left Arm", "Right Arm", "Body"];
for(i=0;i
if (_root[list[i]].hitTest(x, y, true)) {
// Меняем выбранный элемент
with (_root[list[i]]) {
// Переходим к следующему кадру
if (_currentFrame == _totalframes) {
gotoAndStop(1);
} else {
nextFrame();
}
}
break;
}
}
}
Номер кадра и обшее количество кадров определяется при помощи параметров _currentFrame и _totalFrame. Это очень удобно в случае, когда клипы могут включать любое количество кадров, а код -учитывать все возможные варианты.
Конструкция with указывает, что все команды и функции кода в рамках этой конструкции должны выполняться для определенного клипа. Это позволит вам обойтись без добавления _root [movieclip] в начале каждой команды или функции.
Ролик Makeafox-switch.fla можно увидеть на Web-сайте. На рис. 7.4 показан один из возможных вариантов, получившихся в результате внесенных изменений. Независимо от того, сколько раз и в какой последовательности пользователь щелкает по элементам изображения, оно всегда будет оставаться цельным.

Рисунок 7.4 Пользователь может щелкнуть по любой части тела и изменить ее
Код назначен кнопкам, которые размешены внутри переключателей. Первый кадр каждого переключателя содержит код для запуска воспроизведения звука. Помимо этого код задает переход клипа к следующему кадру. Кнопка присутствует во всех кадрах клипа. Различные сценарии используются для остановки звука в цикле барабанов и цикле басов.
Самый простой сценарий - у переключателей отдельных звуков. Задача данного сценария - запустить воспроизведение звука и задать его переход к следующему кадру.
on (press) {
// Указываем, что надо проиграть из библиотеки звук
// соответствующий выбранному клипу.
instanceSound = new Sound(),
instanceSound.attachSound(this._name);
instanceSound.start();
// Начинаем анимацию, показывающую, что кнопка выбрана.
gotoAndPlay(2);
}
}
Обратите внимание, что имя звука описывается при помощи синтаксиса this._name. Это значит, что имя клипа будет являться и именем звука Если клип называется "instance 1", код попытается воспроизвести звук с именем "instance 1". Первое имя "instance 1" соответствует имени клипа на рабочем поле, второе имя "instance 1" является именем соответствующего звука в библиотеке. Эта схема работает только в том случае, если имена полностью совпадают.
Преимущество данного способа заключается в том, что один и тот же клип может использоваться на рабочем поле для воспроизведения различных звуков. Имя звука берется из имени копии клипа, а не из переменной ActionScript, что делает такой клип более универсальным.
Анимация начинается после перехода клипа к следующему кадру. В конце анимации клип возвращается к первому кадру, а находящаяся в нем команда stop () остановит его повторное воспроизведение.
В случае отдельных звуков одна и та же кнопка находится во всех кадрax, что дает пользователю возможность запустить воспроизведение нового звука даже во время воспроизведения анимации клипа.
Клипы для басов и отдельных звуков аналогичны. Основное их различие состоит в том, что первый звук должен периодически повторяться. Для этого в команду start требуется добавить два параметра: смещение от начала звука и количество циклов. В нашем случае смешение не нужно следовательно, оставим его значение равным 0. Периодическое повторение звука необходимо, поэтому соответствующий параметр должен иметь очень большое значение.
Рассмотрим сценарий кадра "record". Он начинается с инициализации массива и определения времени начала записи.
// Определяем массив.
danceArray = new Array();
// Считываем текущее время.
startTime = getTimer();
Функция danceButton вызывается одной из трех кнопок, расположенных внизу экрана. Они определяют время и название танцевального движения и помещают эту информацию в массив. Они также дают команду клипу "fox" (его библиотечное имя - "dance") к исполнению движения.
// Пользователь нажимает одну из "танцевальных" кнопок,
function danceButton(moveName) {
// Промежуток времени, прошедший с начала проигрывания.
thisTime = getTimer() - startTime;
// Помещаем временной интервал и название движения в массив.
danceArray.push({time: thisTime, move: moveName});
// Показываем движение,
fox.gotoAndPlay(moveName);
}
Когда пользователь нажмет кнопку Done, движение "stop" будет помещено в массив и ролик перейдет к кадру "menu".
// Нажимаем кнопку Done.
function stopRecordO {
// Вычисляем временной интервал.
thisTime = getTimerO - startTime;
// Добавляем в массив.
danceArray.push({time: thisTime, move: "stop"});
// Возвращаемся в главное меню.
gotoAndStop("menu");
}
Рассмотрим сценарий кадра "playback". Он начинается с определения времени начала воспроизведения и присваивания переменной dance-step значения 0. Эта переменная содержит номер следующего в очереди танцевального па.
// Определяем время.
startTime = getTimer();
// Начинаем с шага 0.
danceStep =0;
Клип "actions" вызывает функцию danceFrame, которая проверяет состояние последовательности танцевальных движений. Она вычисляет текущее время и сравнивает его со временем запуска следующего движения.
Когда это время наступает, функция проверяет, не является ли это движение командой stop. Если это так, то последовательность завершается. В противном случае клип "fox" переходит на соответствующий кадр, и переменная danceStер увеличивает свое значение на единицу.
// Вызывается при каждом обращении к кадру
// из клипа "actions".
function danceFrame() {
// Вычисляем время.
thisTime = getTimer() - startTime;
// Проверяем момент запуска следующего движения, if (thisTime >= danceArray[danceStep].time) {
// Определяем движение.
move = danceArray [danceStep] .move;
// Если это "stop", возвращаемся в кадр "menu",
if (move == "stop") {
gotoAndstop("menu");
} else {
// В противном случае отображаем движение танца.
fox.gotoAndPlay(move);
// Увеличиваем переменную.
danceStep++;
}
}
}
Создание полной программы рисования
Хотя предыдущая программа демонстрирует продвинутые возможности ActionScript, результат ее работы не очень-то интересен. В программу можно добавить другие фигуры и цвета, а также возможность выводить на печать результаты рисования.
Второй параметр функции lineStyle отвечает за выбор цвета. В предыдущем примере был выбран черный цвет — 0x000000. Префикс Ох сообщает программе, что следующее за ним число надо воспринимать в шестнадцатеричном формате, так же, как это происходит при HTML-верстке. Шесть последних цифр обозначают собственно цвет. Также можно использовать значение цвета, получаемое вызовом функции getRGB. В ролике Drawing-fill.fla я использовал несколько разноцветных кнопок. Каждая из этих кнопок представляет собой клип с кнопкой внутри.
На рис. 7.6 показан вид исходного файла Drawing-fill.fla. Слева расположены кнопки, с помощью которых пользователь может управлять цветом.

Рисунок 7.6 Кнопки в левой части экрана дают пользователю возможность выбрать цвет и фигур
Каждая из этих кнопок создана из одного библиотечного эталона. Когда копия помешается на рабочее поле, можно настроить ее цвет с помощью меню color на панели Properties. Внутри клипа находится кнопка, чтобы отслеживать выбор пользователя. Ниже приведен сценарий кнопки. Значение цвета кнопки помещается в переменную brushcolor. Ее значение затем передается переменной linecolor в клип "actions".
on (release) {
// Определяем цвет.
myColor = new Color(this);
brushColor = myColor.getRGB();
// Передаем значение переменной linecolor клипа "actions"
_root.actions.lineColor = brushColor;
// Определяем позицию рамки.
_root["Color Selection"]._x = this._x;
_root["Color Selection"]._y = this._y;
}
Сценарий кнопки устанавливает координаты клипа "Color Selection", то есть рамки, равными координатам клипа, по которому щелкнул пользователь. При этом вокруг кнопки с выбранным цветом появится контур (рис. 7.6.)
Маленькая кнопка с кружочком посередине служит для выбора режима рисования - с заливкой или без. Клип с этой кнопкой состоит из двух кадров: с пустым и заполненным кружочком. Кнопка содержит сценарий, позволяющий переключаться между кадрами, и определяет переменную fill клипа "actions".
on (release) {
if (_currentFrame ==1) {
gotoAndStop(2);
_root.actions.fill = true;
} else {
gotoAndStop(l);
_root.actions.fill = false;
}
}
С помощью кнопок, определяющих цвета, и кнопки выбора режима (с заливкой/без заливки) пользователь может рисовать разноцветные фигуры. Как и в предыдущем примере, код, необходимый для рисования, содержится в клипе "actions".
Он начинается с определения значения следующих переменных: draw - false, fill - false, linecolor - 0x000000. Также определяются четыре переменные, для которые ограничивают область в которой пользователь может рисовать.
onClipEvent (load) {
// Рисовать или не рисовать?
draw = false;
// Определяем значение fill
fill = false;
// Начальный цвет линии - черный. linecolor = 0x000000;
// Определяем границы области рисования.
хтах = 550;
xmin = 70;
утах = 400;
ymin = 0;
}
При нажатии кнопки мыши курсор начинает оставлять след. Координаты курсора хранятся в переменных х и у. Их значения проверяются, и, если они выходят за фаницы разрешенной области, рисование не происходит.
Переменная linecolor передается функции lineStyle в качестве аргумента, определяющего цвет линии. Если переменная fill имеет значение true, то определяется новый массив. Он содержит координаты всех точек вдоль кривой, которую нарисовал пользователь. Массив состоит из объектов следующего вида: {х: значение, у: значение}. Элементы массива потребуются для создания залитой цветом области.
onClipEvent (mouseDown) {
// Определяем позицию курсора.
х = _root._xmouse;
у = _root . _ymouse;
// Рисуем, если не вышли за границы поля
if ((x>xmin) and (x
draw = true;
// Определяем параметры линии.
_root.lineStyle(1,lineColor,100);
_root.moveTo(x,у);
// Если выбран режим заливки, то создаем массив if (fill) {
fillArray = new Array();
fillArray,push({x:x, y:y});
}
}
}
После того как переменной draw присвоено значение true, продолжаем линию до тех пор, пока пользователь не отпустит кнопку мыши. При каждом обращении к кадру переменным х и у присваиваются текущие координаты курсора. Если эти значения выходят за разрешенные границы, переменные х и у переопределяются. Затем используется команда lineTo для отображения очередного сегмента линии. Если выбран режим заливки, то добавляется новый элемент в массив fillArray.
onClipEvent (enterFrame) {
if (draw) {
// Определяем текущую позицию.
x = _root,_xmouse;
у = _root._ymouse;
// Задаем границы области рисования,
if (x < xmin) x = xmin;
if (x > xmax) x = xmax;
if (y < ymin) у = ymin;
if (y > ymax) у = ymax;
// Рисуем линию.
_root.lineTo(x,у);
// Если выбран режим заливки, то запоминаем точку,
if (fill) {
fillArray.push({х:х, y:y});
}
}
}
Когда пользователь отпускает кнопку мыши, переменная draw принимает, значение false, и рисование прекращается. Если при этом выбран режим заливки, то в цикле просматривается массив fillArray и созданная область перерисовывается. При этом также используются команда beginFill и endFill. В результате область заливается цветом linecolor.
onClipEvent (mouseUp) {
if (draw) {
// Прекращаем рисовать.
draw = false;
// Перерисовываем кривую и заливаем
// получившуюся область,
if (fill) {
// Начинаем с первой точки.
_root.moveTo(fillArray[0].x,fiiiArray[0] .у);
// В цикле определяем область для заливки.
_root.beginFill(lineColor);
for(var i=l;i < fillArray.length;i++) {
_root.lineTo(fillArray[i].x,fillArray[i].y);
}
_root.endFill();
}
}
}
Другой способ состоит в том, что вы можете вызвать команду beginFill до того, как пользователь начнет рисовать, и команду endFill - когда он закончит, вместо того чтобы перерисовывать кривую. Но Flash не очень любит использовать заливку при разных обращениях к кадру, и результат может быть хаотичен. Лучше сохранить кривую, а затем перерисовать ее и создать всю заливку в пределах одного обработчика.
Создание простой программы рисования
Конечный ролик позволит пользователю рисовать, используя различные фигуры и цвета, однако для начала дадим ему возможность нарисовать непрерывную линию.
Мы воспользуемся новыми командами для рисования, появившимися в версии MX. Описание этих команд вы можете найти на панели ActionScript (Objects -> Movie -> Movie Clip -> Drawing Methods) или в окне Reference (справка).
Эти команды как бы имитируют движения пользователя, передвигающего мышь. Сначала используем команду line style для определения толщины и цвета будущей линии. Команда moveTo передвигает указатель точки для рисования по экрану; линия при этом не прорисовывается. И наконец, мы используем команду lineTo для рисования линии из текущей позиции в заданную.
Единственным элементом нашего ролика является клип "actions", который содержит весь необходимый код.
Сценарий начинается с присваивания переменной draw значения false. Эта переменная используется, чтобы определить, рисует пользователь или нет. Затем с помощью linestyle мы задаем толщину и цвет.
Третий параметр команды lineStyle определяет прозрачность линии, то есть свойство alpha. Значение 100 соответствует абсолютно непрозрачному объекту, значение 50 делает объект полупрозрачным.
onClipEvent (load) {
// Рисовать или не рисовать?
draw = false;
// Линия шириной в 1 пиксел, черная, непрозрачная
_root.lineStyle(1,0x000000,100);
}
Когда пользователь нажимает кнопку мыши, переменной draw присваивается значение true. Затем команда moveTo перемещает указатель в текущую позицию курсора. Мы используем конструкцию _root для обращения к свойствам _xmouse и _ymouse, т.к. хотим чтобы центр координат был независим от положения клипа "actions".
onClipEvent (mouseDown) {
// Будем рисовать
draw = true;
// Переходим к координатам курсора.
_root.moveTo(_root._xmouse, _root._ymouse);
}
Когда пользователь отпускает кнопку мыши, переменной draw присваивается значение false, и процесс рисования завершается.
onClipEvent (mouseUp) {
// Завершаем рисование.
draw = false;
}
Значение переменной draw проверяется при каждом обращении к кадру. Если оно истинно, то рисуется линия от предыдущей к текущей позиции курсора.
Константы true и false могут использоваться конструкциями if и for в качестве проверки условия выполнения кода. Вы также можете использовать их для отслеживания объектов, которые могут нахолиться только в двух состояниях (вкл/выкл).
onClipEvent (enterFrame) {
if (draw) {
_root.lineTo(_root._xmouse,_root._ymouse);
}
}
Обратите внимание, что все обращения к командам рисования происходят через конструкцию _root. Это делается для того, чтобы линии рисовались в самом ролике, на рабочем поле, а не на рабочей области клипа "actions". Можно создать отдельный клип "canvas " (холст) и рисовать линии в нем. Прорисовываясь, линии автоматически оказываются на самом заднем плане, так что, если в клипе ( или ролике) есть еще какие-то объекты, они будут закрывать линию. Наверное, вам будет удобней рисовать на пустом уровне.
На рис. 7.5 показана кривая, которая получилась в результате нажатия пользователем кнопки мыши и перемещения курсора. Помните, что скорость рисования соответствует частоте смены кадров ролика, поэтому для того, чтобы процесс рисования проходил плавно, это значение должно быть максимальным и равняться 120 калр/с. Готовый ролик вы можете увидеть, загрузив файл Drawing-line.fla.

Рисунок 7.5 Простая программа рисования позволяет нарисовать длинную черную кривую
Танцующая лиса
Исходный файл: Dance.fla
Вы видели, как пользователь может создавать изображения и последовательности звуков. Попробуем теперь создать последовательность анимаций. В этом примере пользователь создает мультик с танцующей лисой. Во время сеанса записи пользователь может выбрать в режиме реального времени движения, которые будет делать лисица. Каждое движение записывается, и потом пользователь может проиграть созданную им последовательность движений.

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

Рисунок 7.8 Музыкальный миксер состоит из шести циклов барабанов, шести циклов с басами и шести отдельных звуковых эффектов
Задача этого проекта - создать приложение, которое позволит пользователю присоединять части тела лисы к неподвижному туловищу и так составлять изображение зверька. Метод drag-and drop (перетащи и положи) должен быть знаком всем, кто умеет работать с компьютером.
У этой программы есть два режима: запись и воспроизведение. Сначала пользователь использует режим записи и контролирует поведение лисы в режиме реального времени. Он может включить в танец одно из трех разных движений. В перерывах между выбранными движениями лиса исполняет основной танец.
Для завершения записи пользователь может нажать кнопку Done и вернуться в главное меню. Воспроизведение включается кнопкой Playback, после чего в точности воспроизводится записанная последовательность.
Другие возможности
Приведенный здесь пример - игра для совсем маленьких детей. Тем не менее, используемый в ней принцип может быть использован при создании более совершенных игр.
Детям более старшего возраста подойдет игра, целью которой является нахождение чисел или слов какого-либо одного типа. К примеру, задача игры может состоять в выборе глаголов из имеющихся в наличии слов разных частей речи. Другой вариант - географическая викторина, в которой игроку необходимо выбрать определенные страны или места.
В игру легко внести различные изменения. Заданное количество выстрелов можно заменить таймером. Игра может состоять из уровней: игрок будет переходить на другой уровень, поразив определенное количество лис.
Имейте в виду, что игра дает возможность набирать более 50 очков. Каким образом? В ходе игры лисы начинают появляться друг за другом все быстрее и быстрее. Через некоторое время на экране одновременно будут появляться несколько лис. Когда пути двух лис пересекаются, вы можете убить их одним выстрелом, однако это требует сноровки. Если хотите, отмените данное свойство.
В игре могут использоваться некоторые звуковые эффекты и фоновые звуки. Игра будет более интересной, если добавить отвлекающую внимание анимацию, например пролетающую птицу или ветер, раскачивающий ветви.
Чтобы улучшить игру, я увеличил промежутки времени между появлениями лисы. Сейчас они составляют 2 секунды, а должны быть больше двух минут, чтобы игра стала напоминать "Охоту на оленей". Вы можете даже сделать промежутки случайными, чтобы было еще интереснее.
Вместо того чтобы переключать внимание охотника справа налево, вы можете двигаться по кругу. В некотором отношении это может быть проще. Вам не надо беспокоиться о слоях перспективы, как в этой игре. Вместо этого фон может быть одной неподвижной картинкой. Однако, вы также должны найти способ соединять друг с другом левую и правую половины круговой панорамы. Самый простой способ сделать это - заставить правую сторону повторить полную картину вида рабочего поля слева. Тогда, даже если игрок пытается продвинуться дальше вправо, вы просто повторяете весь путь налево. Потребуется немало терпения и труда, чтобы все получилось гладко, но достичь этого возможно.
Имейте в виду, что клипы, изображающие лис, не обязательно должны быть одинаковыми. Сценарий реагирует только на метки "whack" (удар) и "popup" (выглядывающая лиса), а после 24 кадра еще и на начало анимации выглядывающей лисы. Вы можете использовать несколько клипов, изображающих разных лис. Необходимо лишь убедиться, что они достаточно похожи для того, чтобы код мог их обрабатывать, а также присвоить им соответствующие имена при размещении экземпляров клипов на рабочем поле. Использование различных лис сделает игру интереснее.
Завершение игры может быть задано различными способами. В нашем примере ролик воспроизводится, пока интервал между появлениями лис не будет меньше одной секунды, что соответствует появлению 100 лис. Игра может заканчиваться и после того, как произведено определенное количество щелчков. Ваша игра может состоять из нескольких уровней. Поразив заданное число лис, пользователь переходит к другому уровню.
К сведению
Игра включает еще два кода кнопок Play, один для окна начала, другой для окна завершения игры. Кроме того, все кадры содержат команду stop () , запрещающую переход ролика к следующему кадру.
Выбор цвета найденных объектов зависит от фона. В нашем примере фон состоит из зеленого, коричневого и голубого цветов, поэтому для пойманных лис мы выбрали красный цвет.
После создания кода необходимо присвоить копиям клипа имена с "fox0" по "fox6", соответствующие их именам в библиотеке. В нашем примере центр всех клипов с изображениями лис совпадает с центром рабочего поля. Это было сделано следующим образом: анимация была добавлена в главную временную шкалу, выделена, скопирована при помощи команды Edit -> Copy Frames (Редактировать ->Копировать кадры) и вставлена в пустой клип.
Все стандартные части предыдущих игр присутствуют и здесь. Есть окно начала игры с кнопкой в нем. Есть два текстовых поля: очки и оставшиеся выстрелы. Курсор невидим и заменен клипом с изображением р ла. Во всех этих случаях используется код как в игре "Подстрели лису*
Найди лису
Исходный файл: Findafox.fla
В игре "Найди лису" игроку показывают изображение, в котором он должен определить местоположение определенных объектов. В данном случае в ролике Findafox.fla местом действия является лес, а объектами, которые ищет игрок, - лисы.
На первый взгляд игра представляется простой, однако основная ее идея в том, чтобы хорошо замаскировать объекты. На рис. 8.1 показан ролик, изображающий семь лис, спрятанных в лесу.

Рисунок 8.1 Сцена включает семь спрятанных лис, которых должен найти игрок
Охота на лис
Исходный файл: Huntafox.fla
Одна из самых устойчиво популярных долгие годы игр - "Охота на оленей". В этой игре вы часами сидите, наблюдая пейзаж, пока не покажется олень, которого можно будет застрелить. Несмотря на то, что продано миллионы копий этой игры, она достаточно простая. Во Flash можно легко сделать что-нибудь в этом роде.
Подготовка ролика
Наиболее сложная часть создания игры - подготовка фона. Наш ролик состоит из девяти слоев, включающих изображения земли, деревьев и других элементов леса. Использование различных слоев необходимо для того, чтобы лисы могли быть спрятаны за некоторыми из них.
Ролик также включает два вида клипов с лисами. В одном лиса показана при помощи тонких линий, чтобы ее можно было спрятать в нарисованном стволе дерева. Другой представляет собой сплошное изображение лисы, которое появляется на заднем плане. Оба клипа приведены на рис. 8.2.

Рисунок 8.2 Два клипа используются, чтобы прятать лис среди деревьев. Каждый из них используется в зависимости от цвета фона позади лисы
На рабочее поле помещено несколько копий каждого клипа. Они расположены в одном из четырех различных слоев. Кроме основного кадра игра содержит окно начала и окно завершения игры. В обоих окнах есть кнопка, позволяющая пользователю начать игру.
Основной код находится в клипе, расположенном за пределами рабочего поля. Код оперирует именами клипов начиная с "fox()" и заканчивая "fox6".
Имеющиеся 18 отверстий в бревне - это 18 копий одного клипа. Первый кадр данного клипа изображает обычное отверстие. Следующим элементом временной шкалы клипа является анимация лисы, ненадолго выглядывающей из отверстия и затем вновь исчезающей. Другая анимационная последовательность изображает попадание в лису и ее исчезновение. Она запускается, если пользователь успел щелкнуть по лисе (рис. 8.5)

Рисунок 8.5 Игрок только что поразил лису
Для того чтобы код мог управлять 18 клипами, им были присвоены имена от "fox0" до "fox17". Необходимо также создать динамическую текстовую область с именем showScore. На рис. 8.6 изображена панель Properties данной текстовой области.

Рисунок 8.6 Текстовая область связывается с переменной showScore в панели Properties
Наиболее сложным является создание клипов. Чтобы лучше понять, о чем пойдет речь в этом разделе, внимательно изучите ролик Shootafox.fla.
В библиотеке вы увидите три клипа: Peeking Fox (Выглядывающая лиса), Running fox (Бегущая лиса) и Swinging fox (Раскачивающаяся лиса). Каждый из этих клипов состоит из одного кадра или короткой анимации лисы, за которой следует короткая анимация, изображающая удивленную лису, обведенную желтым контуром. Первая часть соответствует, движению живой лисы, вторая часть обозначает, что пользователь зверька. Вторая часть начинается с кадра, имеющего метку "hit". Ролик также включает семь клипов с именами "fox()" - "fox6". Эти клипы содержат внутри себя один из вышеописанных клипов, однако теперь, анимация изображает, как лиса движется по игровому полю или выглядывает из-за дерева. Клипы, расположенные внутри каждого из клипов с именами "fox0" - "fox6", содержат метку "fox", благодаря чему код может обращаться к ним. Для того чтобы показать, что лиса поражена, копия клипа "fox", находящегося внутри клипов "fox0" - "fox6", переходит к кадру "hit".
Большое значение имеет распределение слоев. Ролик состоит из 15 слоев, представляющих собой либо элементы обстановки (в данном случае лес), либо самих лис. Это позволяет прятать лис за одними предметами и показывать перед другими. Отдельные слои зарезервированы для клипов "actions" и "cursor".
В качестве курсора используется клип с изображением перекрестия. За кадром 1, в котором находится простое перекрестие, следует небольшая анимация вспышки, запускаемая во время выстрела игрока. Затем клип возвращается к кадру 1, который содержит команду stop ().
Как и остальные ролики, рассматриваемые в данной главе, этот ролик включает начальное окно игры, саму игру и окно завершения игры.
Структура ролика такая же, как и в предыдущем примере. Четыре слоя "Фон", "Кусты", "Холмы" и "Деревья" - шириной примерно в 1200 пикселов центрованы на рабочем поле шириной в 550 пикселов. Слои Кусты" "Холмы" и "Деревья" Содержат по одному клипу в каждом - они называются "bushes", "hills" и "trees" и включают в себя все элементы соответствующего слоя.
Слоев с лисами два. Один слой содержит лис, прячущихся за кустами, а другой - прячущихся за деревьями. Клипы с лисами за деревьями носят имена от "foxO" до "fox6", а клипы с лисами за кустами - от "fox7" до "fox9".
Клипы с лисами такие же, как в игре "Подстрели лису", только лиса остается видимой гораздо дольше. Чтобы лисы могли прятаться за узкими деревьями, в каждом клипе я использовал слои-маски, позволяющие скрыть те части лисы, которые не должны быть видны.
Изображения лис внутри каждого клипа с лисой такие же, как в игре "Подстрели лису". Однако последний кадр анимации попадания отправляет родительский клип назад к его первому кадру. Это означает что, когда вы попадаете в лису, она исчезает сразу же, как заканчивается анимация попадания.
Подход
Может показаться, что эту игру до смешного легко создать. И действительно, игра бы состояла всего из нескольких кнопок, если бы не следующие два условия: во-первых, необходима обратная связь с пользователем, он должен знать, какие объекты найдены; во-вторых, игра должна распознавать, найдены ли все объекты.
Обратную связь можно создать, применив к клипу, содержащему лису, свойство трансформации цвета. Применив соответствующий цвет, вы добьетесь выделения лисы.
Для того чтобы определить, все ли лисы найдены, используется массив истинных и ложных значений. В начале игры массив содержит семь ложных значений. По мере того, как пользователь будет находить лис, значения станут меняться на истинные. Когда все семь значений массива примут значение true, игрок поймет, что нашел всех лис.
Вместо кнопок мы будем использовать клипы. Кроме того, потребуется управляющий клип со сценарием ActionScript, следящим за нажатием кнопки мыши. Когда нажатие будет обнаружено, функция hitTest кода начнет проверку клипов с изображениями лис и определит, какой из них был выбран. Это происходит аналогично определению выбранного клипа в игре "Составь лису', которая описывалась в главе 7.
Каждое отверстие в бревне представляет собой экземпляр одного клипа. Клип изображает либо пустое отверстие, либо анимацию лисы, выглядывающей из этого отверстия.
Другой клип под названием "actions" управляет очередностью и периодичностью воспроизведения клипов. В начале игры лисы будут выглядывать через каждые две секунды. С каждым разом интервал между появлениями лис немного сокращается.
Когда игрок щелкает по экрану, клип "actions" определяет, какая лиса была выбрана. После этого клип воспроизводит другую анимацию, изображающую лису в состоянии легкого шока.
Каждый раз при появлении лисы значение счетчика увеличивается на один пункт. Когда игрок попадает в лису, значение другого счетчика Taк же увеличивается на единицу. Счет отображается следующим образом: количество попаданий в лису, потом знак /, затем количество появлений лисы. Другими словами, значение "5/12" будет обозначать, что игрок поразил 5 лис из 12.
Поскольку рассматриваемая игра была создана на основе игры "Поймай лису", основная часть кода должна быть вам знакома. Тем не менее, в него были внесены некоторые изменения и дополнения.
Первые изменения касаются способа организации клипов, которые должны содержать анимацию движения и одновременно показывать, произошло ли попадание в лису. Для этого необходимо использовать клип внутри клипа. Вложенный клип имеет два состояния: "поражен" и "не поражен". Во внешнем клипе описывается движение лисы.
В игре отслеживается и обшее количество выстрелов, и количество попаданий. Оба числа отображаются на экране. После того как пользователь израсходует все выстрелы, игра завершается.
Еще одно новшество данной игры - использование необычного курсора. Стандартный курсор мыши спрятан, вместо него виден клип, перемещающийся по рабочему полю за курсором (см. нижнюю часть рис. 8.7).
Все, что вы должны сделать по сравнению с предыдущей игрой, - это позволить пользователю перемешаться по большому фоновому изображению из стороны в сторону. Но это не так-то просто. Одни элементы фона ближе к играющему, чем другие. Чтобы у игрока действительно создалось ощущение движения охотника, близкие объекты должны двигаться быстрее дальних.
Чтобы этого добиться, мы разбиваем элементы фона на четыре группы: близко - деревья, подальше - кусты, еще дальше - холмы, затем - небо и земля. Небо и земля остаются неподвижными. А деревья, кусты и холмы движутся в зависимости от того, насколько далеко они от игрока.
Лисы прячутся за деревьями и в кустах. Это значит, что они должны двигаться вместе с этими элементами. Посмотрите на исходный файл Huntafox.fla на сайте, чтобы понять, как это выглядит. Если вы двигаете курсор вправо по рабочему полю, панорама смешается вправо. Видите, как деревья движутся быстрее кустов, а кусты быстрее холмов? Заметьте также, что деревья иногда затеняют кусты. Хорошему игроку нужно совсем немного подвигать панораму, чтобы убить максимально возможное количество лис. На рис. 8.8 показан случай, когда лиса выглядывает за-за дерева.

Рисунок 8.8. Лиса выглядывает из-за дерева
Подстрели лису
Исходный файл: Shootafox.fla
Рассмотрим еще одну игру из серии "Найди и нажми" - игру-тир. Как и в игре "Найди лису", задача пользователя - щелкнуть по объектам на экране. На игру "Поймай лису" она похожа тем, что объекты появляются на экране в произвольных местах и через произвольный интервал времени.
Но в отличие от предыдущих игр, объекты будут двигаться, лиса будет не просто появляться из отверстия, а бегать, поворачиваться или выглядывать из-за дерева. Игрок должен обладать хорошей реакцией, чтобы попасть по лисе до того, как она снова исчезнет.
На рис. 8.7 показана сцена, очень напоминающая сцену игры "Найди лису". Однако теперь лиса не будет ждать, пока игрок обнаружит ее. Рисунок демонстрирует кадр анимации, в которой лиса быстро перебегает из одной части экрана в другую.

Рисунок 8.7 В игре "Подстрели лису" лиса перемешается по игровому полю
Создание кода
При загрузке клипа в нем создается массив found. Следующий код заполняет массив значениями false:
onClipEvent (load) {
// Создаем массив, в который записываем, какие лисы
// найдены.
found = [];
for (i=0; i<7; i++) {
found[i] = false;
}
}
При нажатии кнопки мыши положение курсора сохраняется в переменных х и у. Затем при помощи функции hitTest эти значения соотносятся с координатами клипов лис. Когда совпадение найдено, соответствующее изображение становится красным. Этого достаточно, чтобы изображение спрятанной лисы выделилось из фона. Каждый щелчок мышью запускает проверку массива found на наличие значения false. Это означает, что, по крайней мере, одна лиса еще не найдена. Когда все лисы найдены, клип переходит к следующему кадру:
onClipEvent (mouseDown) {
// Определяем, в каком месте пользователь щелкнул мышью.
х = _root._xmouse;
у = _root._ymouse;
// Проверяем, какое изображение лисы найдено,
for (i=0; i if (_roott"fox"+i],hitTest(x, y, false)) {
// Изменяем цвет лисы.
myColor = new Color(_root["fox"+i]);
myColor.setTransform({rb:128,bb:0,gb:0});
// Запоминаем, что лиса найдена.
found[i] = true;
break;
// Проверяем, все ли лисы найдены.
gameover = true;
for (i=0; i if (found[i] == false) {
// Если хотя бы одна еще не найдена,
// игра не закончена.
gameover = false;
//если пользователь выиграл.
// Заканчиваем игру,
if (gameover) {
_root.gotoAndPlay ("Game Over");
}
}
Команда break используется в цикле for и других для его немедленной остановки. Это удобно, когда по той или иной причине необходимо остановить цикл. В вышеприведенном коде цикл проходит значения от 0 до 6, но может завершиться в случае, если функция hitTest примет значение true.
Весь код данной игры назначен клипу "actions", расположенному за пределами рабочего поля. Он начинается с инициализации всех глобальных переменных. В начале ролика интервал появления лис равен 2 секундам (2000 миллисекундам).
onClipEvent (load) {
// Указываем промежуток времени между появлениями лис.
timeBetweenFoxes = 2000;
// Определяем время до появления следующей лисы.
nextFox = getTimer() + timeBetweenFoxes;
// Инициализируем переменные пораженных и показанных лис.
score = 0;
numFoxes = 0;
}
Функция getTimer () - это своеобразные часы. Функция возвращает количество миллисекунд, прошедших после начала ролика. Значение этих часов постоянно увеличивается, поэтому данную функцию удобно использовать для управления временными интервалами в вашей игре.
Функция onClipEvent (enterFrame) определяет, наступило ли время для появления следующей лисы. Затем она выбирает такое новое отверстие, которое не используется в данный момент. Интервал времени между появлениями лис сокращается на 10 миллисекунд, в результате чего игра с каждым разом все больше ускоряется. Если значение интервала составляет менее 1000 миллисекунд, игра завершается. За 150 секунд пользователь получает 100 возможностей поразить лису.
onClipEvent (enterFrame) {
// Определяем, не пора ли показывать следующую лису,
if (getTimerO >= nextFox) {
// Сокращаем время между показами.
timeBetweenFoxes -= 10;
// Выясняем, не пора ли заканчивать игру,
if (timeBetweenFoxes < 1000) {
_root.gotoAndPlay("End") ;
// Если нет, показываем следующую лису.
} else {
// Увеличиваем счетчик показанных лис.
numFoxes++; _root.showScore = score + "/" + numFoxes;
// Определяем, какая лиса покажется,
while (true) {
fox = Int (Math.Random0*18) ;
if (_root["fox"+fox]._currentFrame == 1) break;
// Выбранная лиса появляется из отверстия.
_root ["fox"+fox].gotoAndPlay ("popup") ;
// Устанавливаем время появления следующей лисы.
nextFox = getTimerO + timeBetweenFoxes;
Как и в предыдущих примерах, основной код назначен клипу "actions". Первая часть кода - функция onClipEvent (load). Клип устанавливает счета на 0 и инициализирует переменную shotsLeft, которой присваивается значение 50. Это позволяет игроку сделать 50 выстрелов и убить как можно больше лис. Переменная shotsLeft используется для отображения счета на экране, а переменная showshotsLeft, связанная с текстовой областью, отображает, сколько выстрелов осталось у игрока.
При помощи функции Mouse.hide () в блоке onClipEvent (load) скрывается курсор мыши.
onClipEvent (load) {
// Задаем время между появлениями лис.
timeBetweenFoxes = 2000;
// Вычисляем, когда должна появиться следующая лиса.
nextFox = getTimer()+timeBetweenFoxes;
// Инициализируем переменную, содержащую количество
// попаданий и число выстрелов.
score = 0;
shotsLeft = 50;
_root.showScore = "Score:"+score;
_root.showShotsLeft = "Shots Left:"+shotsLeft;
// Прячем курсор.
Mouse.hide();
}
Использование объекта Mouse позволяет контролировать видимость курсора, расположенного над рабочим полем ролика. При помощи команды Mouse.hide() вы можете скрыть курсор, при помощи команды Mouse. show () - вновь вывести его на экран. Так как курсор скрыт, его необходимо заменить чем-нибудь, чтобы игрок видел, по какому месту экрана он щелкает. В данном случае клип "cursor" ставится в соответствие положению курсора мыши. В остальном функция onClipEvent (enterFrame) повторяет аналогичную функцию игры "Поймай лису".
onClipEvent (enterFrame) {
// Передвигаем курсор.
_root["cursor"]._x = _root._xmouse;
_root["cursor"]._y = _root._ymouse;
// Проверяем, не пора ли показывать следующую лису
if (getTimer()>=nextFox) {
// Сокращаем время до следующего появления лисы.
timeBetweenFoxes -= 5;
// Проверяем, не завершена ли игра
if (shotsLeft < 1) {
_root.gotoAndPlay("End");
// Если нет, показываем новую лису.
} else {
// Задаем появление новой лисы,
Хотя и клипы и слои отличаются от тех, что использованы в игре "Подстрели лису", основной сценарий этой игры применим и в нашем случае. Это сценарий, назначенный клипу "actions". Необходимо внести только два изменения, и я не буду приводить здесь весь код. Первое изменение состоит в том, что теперь можно выбирать из 10, а не из 7 лисиц, поэтому число внутри функции Math.random должно быть 10.
Второе изменение обращает внимание на положение курсора, так что сцена перемешалась, если пользователь двигает курсор вправо или влево. В этом случае вызывается функция moveScene на корневом уровне. Она принимает значения -1 или 1 в зависимости от направления движения.
// Перемещаем панораму,
if (_root._xmouse < 50) {
_root.moveScene(1);
} else if (_root._xmouse > 500) {
_root.moveScene(-1);
}
Клип "moveScene" находится на главной временной шкале. Этот сценарий начинается с определения нескольких переменных. panAmount отслеживает расстояние, на которое пользователь сдвинулся вправо или влево. Например, если пользователь двигается влево, тогда графика движется вправо и panAmount принимает значение 1. Если он продолжает двигаться в этом направлении, panAmount увеличивается до 2, -, и т.д. Если пользователь движется в противоположном направлении, panAmount принимает значения -1, -2 и так далее.
Поскольку мы не можем нарисовать бесконечно широкую сцену, нам приходится задавать границы панорамирования. Две переменные содержат максимально разрешенное передвижение влево и вправо. Я определил эти границы путем проб и ошибок. Начал я с 50 и увидел, что игрок может доходить до конца деревьев. Тогда я начал пробовать меньшие числа, пока игрок не перестал вылезать за границы сцены.
panLimitLeft = -30;
panLimitRight = 30;
panAmount = 0 ;
Чтобы перемешаться по сцене, сначала проверяется, не превышает ли следующее значение panAmount допустимые границы. Функция работает только в том случае, если следующее значение находится в пределах допустимого.
Потом три клипа - "trees", "bushes" и "hills" - перемещаются в нужном направлении. Деревья перемещаются с коэффициентом (фактически скоростью) 10, кусты - с коэффициентом 5 и холмы - 4. Я подобрал эти значения путем проб и ошибок. По-моему, они создают достаточное ощущение глубины.
Первые 7 лисиц, которые находятся прямо за деревьями, движутся с ними вместе с коэффициентом движения 10. Остальные три лисы перемещаются с коэффициентом 5, поскольку сидят за кустами.
Когда игрок находит лису, он
Когда игрок находит лису, он должен выбрать ее щелчком мыши. Если пользователь сделал правильный выбор, он должен это увидеть. Он также должен знать, какую лису нашел.
После того как все семь лис найдены, игра должна автоматически перейти в новое окно. Это значит, необходимо следить за тем, какие объекты найдены, а какие нет.
Задача игры состоит в том, чтобы отверстие, в котором появляются объекты, выбиралось программой произвольным образом. Лиса может показаться в любом из 18 отверстий и почти сразу же исчезнуть.
На рис. 8.4 показан кадр анимации игры. В то время, когда лиса выглядывает, пользователь должен щелкнуть по ней и получить очки.
Игра ведется на время и счет.

Рисунок 8.4 Одна из лис выглянула из отверстия
За основу данной игры взята игра "Поймай лису". Лисы постоянно бегают из одной части игрового поля в другую. Мы будем использовать три анимационных последовательности: лиса перебегает с места на место, раскачивается под деревом и выглядывает из-за дерева. Каждая анимация используется два или три раза, различные их комбинации составляют семь возможных анимаций, воспроизводящихся во время игры.
С интервалом в две секунды и менее запускается одна из анимационных последовательностей, и игрок получает возможность щелкнуть по лисе. Анимация должна продолжиться, показав перед этим, попал ли игрок в цель.
Игра должна отслеживать количество сделанных выстрелов и количество попаданий, а также задавать ограничение на число произведенных выстрелов. Курсор следует сделать не в виде стрелки, а в виде прицела ружья.
Задача состоит в том, чтобы сделать игру - стрелялку, позволяющую пользователю передвигаться влево и вправо по пространству, большему, чем способно вместить в себя рабочее поле экрана. Мишени возникают в случайное время и в случайных местах, вне зависимости от того, куда сейчас смотрит игрок. Перемещение должно создавать игроку иллюзию пространства, так чтобы близкие объекты двигались быстрее далеких.
Другие возможности
Существует несколько способов усовершенствования этой игры. Вы можете ускорять падение яблок, задать интервал между падениями двух яблок или изменить общее количество бросаемых яблок.
Вы также можете использовать другое изображение лисы и иначе настроить функцию moveapples, увеличивая или уменьшая размер корзины для яблок.
Сообразительный программист наверняка изобразит корзину, наполняющуюся яблоками по мере их попадания, и заставит лису время от времени высыпать собранный урожай в определенном месте экрана. В следующем разделе будет рассмотрена игра, созданная на основе данной, но в ней будут и плохие яблоки, которые нельзя ловить.
Это обучающая игра и, к сожалению, подходит лишь для маленьких детей, еще не выучивших алфавит. Однако вы можете изменить содержимое каждого кадра, содержащего хорошее или плохое яблоко. Одним из вариантов может быть увеличение яблока, для того чтобы на нем могла поместиться более длинная фраза.
Вариантом для детей более старшего возраста могут быть яблоки, включающие глаголы и существительные. Они также могут содержать четные и нечетные числа, числа кратные трем или сокращаемые дроби. Дети еще более старшего возраста могут выбирать страны определенного континента или названия деревьев. Игра может иметь любую тему, главное, чтобы на вопросы можно было дать ответ "верно/неверно".
Так как столкновение замедляет скорость игры, она представляет собой идеальный вариант игры на время. Начало игры можно обозначить при помощи объекта date (см. раздел "Аналоговые часы" в главе 6). Теперь вы будете знать, сколько игроку требуется времени для прохождения игры. На скорость байдарки может влиять не только столкновение со скалой. Соответственно изменив код, вы можете сделать так, чтобы байдарка набирала скорость только при движении вперед. Это сделает игру более захватывающей.
Вы можете создать другой вариант данной игры: попробуйте изменить направление движения объектов, вместо байдарки используйте машину или велосипед, а реку замените дорогой. Получится хорошая игра-гонка
Игра уже достаточно сложна для примера в книге. Однако существует много мелких деталей, которые вы можете добавить, чтобы она стала еще более увлекательной. Например, вы можете изменить холмы фона в клипе и заставить их увеличиваться по мере приближения машины. Это создаст иллюзию, что машина подъезжает к холмам.
Вы можете добавить разные типы бонусов, стоящие разное количество очков. Вы также можете ограничить скорость машины, но ввести бонусы, позволяющие эту скорость увеличить.
Гонки
Исходный файл: Racing.fla
Чтобы сделать из игры "Сплав на байдарке" игру "Гонки", надо просто изменить графику и ничего больше. Замените байдарку на машину. Замените кадры с поворотами, чтобы показывать поворот колес машины, а не поворот байдарки в другом направлении. Замените кадр перевернувшейся лодки на кадр автокатастрофы и т.д.
Однако мы можем использовать похожую технику для создания гоночных игр разных типов. Вместо вида на дорогу сверху мы можем сделать вид с водительского места. Дорога движется к игроку (см. рис 9.9).

Рисунок 9.9 В игре гонки дорога движется по направлению к игроку
К сведению
Вышеприведенный код использует установленный по умолчанию размер рабочего поля для ролика - 550x400. Если вы хотите указать другой размер, необходимо внести соответствующие изменения в код. Вы также можете настроить левую и правую границу игрового поля. Выше приведенный код ограничивает расположение яблок и лисы по вертикали диапазоном между 30 и 520 пикселами, задавая ширину границы, размером 30 пикселов. Вы можете их увеличить или уменьшить.
Для остановки анимации первый кадр клипа лисы должен содержать команду stop (). Не забудьте также вставить команду gotoAndPlay в последний кадр клипа.
Ролик содержит динамическую текстовую область, связанную с переменной score, поэтому отображение счета не составит проблемы.
Полная игра (файл Applecatch.fla), состоит из трех кадров. Первый является кадром начала игры и содержит команду stop(). При помощи соответствующей кнопки осуществляется переход к кадру "Play", в котором происходит основное действие игры. Затем следует кадр "Game Over". В отличие от предыдущих игр, использующих различные сцены, кадры данной игры находятся в одной и той же. Но вы можете использовать вариант и с различными сценами.
Как и в игре "Поймай яблоко" перед и после кадра "play" находятся соответственно кадры "start" и "game over". He забудьте также о текстовой области "score" и других компонентах, упомянутых в разделе "К сведению" для предыдущей игры.
Данная игра содержит два кадра, обозначающих конец игры. Первый кадр имеет метку "lose" и содержит сообщение для игроков, которые столкнулись с большим количеством камней и проиграли игру. Второй кадр, помеченный как "win", содержит сообщение для тех, кто миновал все камни. Кадры отличаются только текстом. Оба кадра содержат кнопку "Play" для перезапуска игры.
Ролик-пример содержит вводный кадр и в нем кнопку начала игры. Третий кадр содержит сообщение "Game over" и не включает в себя клип с бонусом, который содержится только во втором кадре. Это предотвращает получение игроком очков после окончания игры. Я также добавил в ролик-пример фоновый пейзаж.
Подготовка ролика
Фон ролика представляет собой сложное изображение, которое, однако, не играет никакой роли. Активными элементами игры являются только яблоки и лиса. Эталоны этих клипов хранятся в библиотеке, но ни один из них не размешается на рабочем поле. Они создаются при помощи кода по мере необходимости.
Клип, содержащий яблоко, представляет собой статическое изображение. Клип с лисой более сложный. Его первый кадр, помеченный "stand", содержит изображение неподвижной лисы. Второй кадр, "run", представляет собой начало анимации, в которой ноги лисы двигаются. В последнем кадре анимации содержится функция gotoAndPlay, возвращающая клип к кадру "run". В результате мы имеем два варианта поведения клипа с лисой: первый- клип остается в кадре 1; второй запускает анимацию всех кадров, начиная с кадра 2.
Так как и лиса, и яблоки появляются в ролике только после соответствующего запроса кода, в диалоговом окне Linkage properties содержащим их эталонам необходимо назначить свойство "Export for ActionScrip. Яблоко получает идентификатор "apple", лиса - идентификатор "running fox".
Вместо клипа "apples" мы будем использовать клип "rocks". В ролике Riverkayak.fla клип "rocks" состоит из трех кадров. Каждый кадр содержит анимированное изображение, состоящее из другого элемента библиотеки. Хотя каждый камень находится в одном кадре клипа, анимация воспроизводится в графическом элементе. Запустив ролик, вы увидите, что в каждом кадре вокруг камня течет вода.
Клип лисы , ловящей яблоки, будет заменен на клип лисы в байдарке Первый кадр изображает лису в байдарке, повернутой вниз по течению и с веслами над водой. Затем следуют кадры "left" и "right", содержащие изображение повернутой байдарки и одного весла, опущенного в воду. На рис.9.7 изображена лиса, поворачивающая вправо. После этого в кадре 4 запускается анимация "spill", представляющая удар байдарки о камень.

Рисунок 9.7 Второй кадр ролика лисы содержит изображение лисы, поворачивающей вправо
Для того чтобы клипы "rocks" и "fox" были включены в ролик, им аналогично клипам "apples" и "fox" предыдущих игр необходимо присвоить имена в панели Linkage Properties.
Фон и линии, обозначающие границы дороги, - неподвижные элементы. Но для камней и звездообразных меток нужны клипы. Клип центральной линии - это просто линия, но расположенная таким образом, чтобы центральная точка клипа была на вершине линии.
Машина сама по себе нуждается в трех кадрах.- прямое движение, левый и правый повороты, которые используются, чтобы показать, что машина поворачивает.
Клипы камней и бонусных меток должны быть помещены под нижней границей экрана и названы "SideObject" и "bonus". Клип машины следует поместить внизу экрана и назвать "саг". Кроме того, слева находится клип "actions". Во всех четырех клипах содержатся сценарии.
На экране должны быть два динамических текстовых поля: "timeDisplay» и "score". Они оба должны быть привязаны к переменным с такими же именами.
В ролике-примере я обозначил вводный кадр как кадр 1, таким образом, все действие начинается с кадра 2. Есть еше третий кадр с меткой "game over".
Подход
Для управления перемещением лисы используется объект Key. Он определяет, удерживает ли игрок клавишу (со стрелкой "вправо" или "влево"). Для создания объектов-яблок используется функция attachMovie. Яблоки помешаются в произвольные места в верхней части экрана, а затем начинают падать и либо ловятся лисой, либо достигают нижней границы экрана.
После создания яблока значение счетчика timesinceLastapple сбрасывается на 0. При каждом новом обращении к кадру его значение увеличивается. Следующее яблоко создается только тогда, когда счетчик принимает значение 20. Это означает, что яблоко может быть создано только через 20 кадров после появления предыдущего. Скорость падения яблока определяется переменной appleSpeed. Каждый раз при падении яблока переменная увеличивается. Таким образом, чем дольше длится игра, тем быстрее падают яблоки. Клип яблока удаляется либо после попадания в корзину, либо при достижении нижней границы экрана. Для того чтобы определить, попало ли яблоко в корзину, координаты яблока сравниваются с координатами корзины. Для облегчения вычислений центр координат клипа с лисой находится в середине корзинки. На рис. 9.2 показан этот клип (его центр отмечен крестиком).
После сбрасывания определенного количества яблок игра заканчивается. Счетом будет служить количество пойманных яблок, отображаемое в правом верхнем углу экрана.

Рисунок 9.2 Центр координат клипа с лисой находится в середине корзинки
В игре "Поймай яблоко" единственный клип яблока в библиотеке содержал статическое изображение, состоящее из одного кадра. Для показа различных типов яблок нам понадобится два разных клипа, один для хороших яблок, другой для плохих. Кроме этого, каждый клип будет состоять из множества кадров с изображениями различных яблок. Клип хорошего яблока будет состоять из 5 кадров, соответствующих гласным. Клип плохого яблока будет состоять из 20 кадров, представляющих согласные звуки. Буква "Y" использоваться не будет.
Когда наступает время бросать яблоко, оно может с равной степенью вероятности оказаться как хорошим, так и плохим. Код отобразит произвольный кадр из соответствующего клипа.
После того как игрок поймает яблоко, код определит его тип и соответственно изменит счет. Подготовка ролика
В библиотеке ролика вы увидите два клипа яблока. Первый, "bad apple", содержит 20 кадров. Каждый кадр включает изображение яблока и согласной. Другой клип, "good apple", содержит 5 кадров для 5 гласных. На рис. 9.5 изображено основное окно Flash, открытое на клипе "bad apple".
В диалоговом окне Symbol Linkage Properties обоим клипам будет назначено свойство Export for ActionScript и присвоен идентификатор "good apple" или "bad apple".
Прежде всего, код необходимо изменить таким образом, чтобы объекты двигались не вниз, а вверх. Далее, весь код, связанный со столкновениями, необходимо привести к одной форме, рассматривающей любое столкновение как плохое.
Остальные изменения незначительны. Левая и правая границы должны двигаться, отображая камни в реке. Скорость игры может быть больше, и на экране одновременно может отображаться больше камней.
Вместо постепенного ускорения скорость игры будет падать до 0 при столкновении. В результате игрок почувствует удар. В конце игры будет такое же замедление.
Иллюзия глубины может быть достигнута простым использованием перспективы. На рисунке 9.9 показано, что границы дороги нарисованы диагонально по направлению к нижним углам экрана. Хотя ширина дороги предполагается постоянной, глазу кажется, что дорога спереди уже.
В дополнение к линиям, все элементы игры должны появляться с некоторого расстояния. Это означает, что они должны двигаться не только сверху вниз, но и в стороны. Сыграйте прямо сейчас, чтобы посмотреть, как движутся камни по краям дороги и дорожные метки, похожие на звезды.
Три типа элементов движутся в этой игре: камни по сторонам дороги, звездообразные "бонусы"-метки на дороге и центральная линия дороги. В зависимости от скорости машины камни движутся по экрану вниз быстрее или медленнее. Движение камней в сторону - разбегание, создающее иллюзию перспективы, - происходит с той же скоростью, что и вниз.
Звездообразные метки располагаются ближе к центру экрана, поэтому они движутся в стороны не так быстро, как вниз; скорость их движения в стороны составляет половину от значения скорости движения вниз. Это соответствует перспективе, заданной сторонами дороги. Центральная линия просто движется прямо вниз.
Все эти элементы повторяются в игре раз за разом. Например, как только камень достигает нижней границы экрана, он снова появляется на горизонте и опять движется к игроку.
В дополнение к движению трех элементов игры мы также изменяем их масштаб. Таким образом, объекты, которые предполагаются далекими, выглядят меньше и увеличиваются по мере приближения.
Наша цель не в том, чтобы создать перспективу, реальную до последнего пиксела, а в том, чтобы достаточно к ней приблизиться, предоставив возможность воображению пользователя довершить остальное и почувствовать себя въезжающим в экран.
Поймай яблоко
Исходный файл: Applecatch.fla
В первой игре "Поймай яблоко" лиса будет двигаться в нижней части экрана и пытаться поймать яблоки, падающие с дерева. На рис. 9.1 показан фрагмент игры. Полный ролик находится в файле Applecatch.fla.

Рисунок 9.1 Элементами игры "Поймай, яблоко" являются лиса в нижней части экрана и яблоки, падающие сверху
Создание кода
Как и в большинстве наших игр, все события данной игры запускаются при помощи клипа "actions". В нашем примере этот клип расположен за пределами рабочего поля в верхнем левом углу экрана.
Сценарий, назначенный клипу "actions", вызывает функции главной временной шкалы ролика. Это упрощает код, так как перед именами клипов не нужно добавлять префикс _root. После зафузки клипа код вызывает функцию initGame, а затем вызывает три функции при каждом обращении к кадру.
onClipEvent (load) {
root.initGame();
}
onClipEvent (enterFrame) {
_root.moveFox();
_root.dropNewApple();
_root.moveApples();
}
Таким образом, вся работа осуществляется четырьмя функциями, которые находятся в главной временной шкале. Рассмотрим каждую из них.
Первая функция, initGame, инициализирует в начале игры целый ряд переменных. Она создает и клип с лисой. Этот клип создается при помощи кода, а не добавляется при создании ролика потому, что лиса должна располагаться поверх яблок. Если бы клип лисы создавался одновременно с роликом, тогда каждое яблоко, созданное кодом, помещалось бы поверх лисы. Это позволяет нам управлять размещением уровня, в котором содержится лиса, относительно уровня с яблоками. Лисе отведен уровень 999,999. Яблоки будут помешаться начиная со слоя 1 и, следовательно, будут располагаться под лисой.
function initGame() {
// Инициализация переменных, хранящих
// номера первого и последнего яблока.
firstApple = 1;
lastApple = 0;
// Инициализация переменной, хранящей число пойманных яблок,
score = 0;
// Указываем общее количество яблок.
totalApples =20;
// Скорость падения и счетчик времени
// между появлениями яблок.
timeSinceLastApple = 0;
appleSpeed = 5;
// Создаем экземпляр клипа содержащий лису,
attachMovie ("running fox", "fox", 999999);
fox._x = 275;
fox._y = 300;
}
Для того чтобы переместить лису, объект Key должен проверить состояние клавиатуры. С помощью функций Key. isDown (Key.RIGHT) и Key. isDown (Key.LEFT) проверяется, нажаты ли стрелки "вправо" и "влево" соответственно. Переменная dx принимает значение от 10 до -10 и показывает насколько и в каком направлении должна переместиться лиса.
Код клипа "actions" аналогичен тому, что использовался в игре "Помай яблоко". Изменятся только функции. В функцию initGame было внесено лишь одно изменение: число падающих яблок было увеличено до 50.

Рисунок 9.5 Клип "bad apple" состоит из 20 кадров. Каждый кадр содержит изображение яблока и одного из согласных звуков
function initGame() {
// Инициализация переменных, хранящих
// номера первого и последнего яблока.
firstApple = 1;
lastApple = 0;
// Инициализация переменной, хранящей число пойманных яблок,
score = 0;
// Задаем общее количество яблок.
totalApples = 50;
// Скорость падения и счетчик времени между появлениями яблок.
timeSinceLastApple = 0;
appleSpeed = 5;
// Создаем экземпляр клипа, содержащий лису.
attachMovie("running fox","fox",999999);
fox._x = 275;
fox._y = 300;
}
Функция moveFox полностью совпадает с аналогичной функцией игры "Поймай яблоко", поэтому нет смысла повторять ее здесь. Функция drop-NewApple будет отличаться, так как она должна выбирать, какое яблоко бросать, а затем отображать произвольный кадр выбранного клипа.
function dropNewApple() {
// Проверяем, прошел ли заданный промежуток времени,
if (timeSinceLastApple > 20) {
// Бросаем яблоко, если не превышено
// их предельно допустимое количество,
if (lastApple < totalApples) { // Устанавливаем вероятность сброса яблока в 10%.
if (Math.random() < .1) {
// Создаем объект-яблоко.
lastApple++;
if (Math.random() < .5) {
//В 50% случаев яблоко плохое.
attachMovie( "bad apple", "apple"+lastApple, lastApple);
_root["apple"+lastApple].type = "bad";
} else {
// В 50% случаев яблоко хорошее.
attachMovie( "good apple", "apple"+lastApple, lastApple);
_root["apple"+lastApple].type = "good";
}
f=int(Math.Random()*_root["apple"+ lastApple]._totalFrames) + 1;
trace(f);
_root["apple"+lastApple].gotoAndStop(f) ;
Клипу "actions" назначен такой же сценарий, как и в первых двух играх данной главы, однако имена были изменены в соответствии с темой данной игры.
onClipEvent (load) {
_root.initGame();
}
onClipEvent (enterFrame) {
_root.moveFox();
_root.newRock();
_root.moveRocks();
}
Функции главной временной шкалы должны быть вам знакомы. Некоторые части кода аналогичны функциям, рассмотренным ранее, но имеют другие имена.
Функция initGame запускает игру со скоростью течения реки 0. Изображение лисы расположено не в нижней части экрана, а в центре.
function initGame() {
// Номера первого и последнего камня.
firstRock = 1;
lastRock = 0;
// Задаем переменную, содержащую количество столкновений.
spills = 0;
// Количество камней.
totalRocks = 50;
// Время, прошедшее со времени появления последнего камня.
timeSinceLastRock = 0;
riverSpeed = 0;
/// Помещаем на рабочее поле клип лисы.
attachMovie( "kayaking fox", "fox", 999999 );
fox._x = 275;
fox._y = 200;
}
Как и в предыдущих примерах, функция moveFox определяет, нажаты ли клавиши со стрелками "влево" и "вправо". Кроме этого, она проверяет, воспроизводится ли анимация "spill", и если ответ положительный, игнорирует нажатие клавиш.
Вместо поворота изображения код задает переход клипа "fox" к кадрам, помеченным "left" или "right". Первый кадр имеет метку "still" и отображает байдарку, плывущую вперед.
function moveFox() {
if (fox._currentFrame > 4) {
//Во время столкновения нажатие клавиш игнорируется.
dx = 0;
} else if (Key.isDown(Key.RIGHT)) {
// Передвигаем лису вправо.
dx = riverSpeed;
fox.gotoAndStop("left");
} else if (Key.isDown(Key.LEFT)) {
// Передвигаем лису влево dx = -riverSpeed;
fox.gotoAndStop("right");
} else {
// Клавиша не нажата.
dx = 0; fox.gotoAndStop("still");
}
// Передвигаем лису и отслеживаем,
// чтобы она не вышла за границы экрана.
fox._x += dx;
Основная часть кода - это сценарий клипа машины. Он начинается с задания переменной speed значения 0. Эта переменная должна быть на уровне _root, поскольку остальные клипы будут к ней обращаться.
onClipEvent(load) {
// Инициализируем переменную скорости.
_root.speed = 0;
}
Обработчик onClipEvent (enterFrame) сначала проверяет все четыре клавиши с изображением стрелок. Левая и правая клавиши со стрелкой перемешают машину влево или вправо и также заставляют клип с машиной показывать соответствующий кадр поворота.
Клавиши со стрелками вверх и вниз изменяют скорость машины на 0,1. Постоянно осуществляется проверка, не упала ли скорость ниже 0.
Если ни одна из клавиш со стрелками не нажата, клип с машиной возвращается к первому кадру. Обработчик осуществляет еще две проверки. Первая нужна, чтобы узнать, не находится ли под машиной клип "bonus". Если да, игрок получает очки, и бонус очень быстро проезжает далее, чтобы игрок не получил за него очки еще раз.
Вторая проверка выясняет, не коснулась ли машина обочины. Если да, движение машины в сторону ограничивается и замедляется.
onClipEvent(enterFrame) {
if (Key.isDownfKey.LEFT)) {
// Поворачиваем влево.
this._x -= 10;
this.gotoAndStop("left");
} else if (Key.isDown(Key.RIGHT)) {
// Поворачиваем вправо.
this._x += 15;
this.gotoAndStopC'right") ;
} else if (Key.isDown(Key.UP)) {
// Увеличиваем скорость.
_root.speed += .1;
} else if (Key.isDown(Key.DOWN)) {
// Тормозим.
_root.speed -= . 1;
// Проверяем, что скорость не меньше 0.
if (_root.speed < 0) _root.speed = 0;
} else {
_root.car.gotoAndStop("straight");
// Проверяем бонус.
if (this.hitTest(_root.bonus._x,_root.bonus._y)) {
_root.score++;
_root.bonus._y +=100;
// Замедляем движение, если коснулись обочины,
if (this._x < 80) {
this._x = 80;
_root.speed /= 2;
} else if (this._x > 470) {
this._x = 470;
_root.speed /= 2;
}}
Клип "sideObject" содержит сценарий, двигающий объект вниз и в сторону от центра. Для каждого следующего кадра значение _у увеличивается, а _х - изменяется. Оба параметра используют переменную speed для характеристики этого изменения, но _х использует коэффициент dx который может быть равен 1 или -1. Объект перемешается соответственно вправо или влево.
Когда объект достигает значения 600 по вертикали, что на 200 пикселов ниже границы экрана, он возвращается назад к значению 200, то есть вновь появляется на горизонте. С вероятностью 50/50 он помещается слева или справа от дороги. Именно в этот момент определяется значение переменной dx.
И наконец, масштаб объекта определяется в соответствии со значением _у. Это означает, что объект становится больше по мере приближения
Сплав на байдарке
Исходный файл: Riverkayak.fla
В этом разделе данной главы мы, используя код двух предыдущих игр, создадим совершенно другую на первый взгляд игру. В этой игре наш герой лиса будет плыть по реке на байдарке, избегая препятствия и стараясь добиться хорошего времени.
Для трансформации предыдущих игр в эту, как ни удивительно, не нужно прилагать много усилий. И в то же время игры будут совершенно разными. Взглянув на рис.9.6, вы убедитесь, насколько данная игра отличается от игр "Поймай яблоко".
Лисой можно управлять при помощи
Лисой можно управлять при помощи клавиш "влево" и "вправо". Лиса будет передвигаться в течение всего времени, пока пользователь удерживает одну из клавиш. Перед правой или левой границей экрана лиса автоматически остановится.
Яблоки падают из произвольных мест верхней части экрана и через произвольный интервал времени, но не слишком часто. Вначале яблоки падают медленно, но в ходе игры скорость их падения увеличивается. После того как упадет определенное количество яблок, игра завершается. Счет будет равен количеству пойманных лисой яблок.
Задача проекта - так изменить игру "Поймай яблоко", чтобы учитывалось различие букв (гласные/согласные). Поймав любое яблоко с нарисованной гласной буквой, игрок получит очко, поймав яблоко с согласной, он потеряет очки. При этом счет не может быть меньше 0.
Одной из задач данной игры является создание определенной иллюзии у игрока. Хотя байдарка остается в центре экрана, у игрока складывается впечатление, что она движется вниз по реке. Это достигается при помощи объектов, двигающихся вверх по экрану.

Рисунок 9.6 Игра "Сплав на байдарке" состоит из байдарки в центре экрана и камней и веток деревьев, несущихся ей навстречу
Большая часть кода будет взята из двух игр, рассмотренных ранее в данной главе. Однако, в отличие от предыдущих игр, избегать придется все, а не только некоторые объекты. Счет будет содержать не количество набранных очков, а количество столкновений байдарки с объектами. Чем больше произойдет столкновений, тем скорее закончится игра.
Главная задача этой игры - создание иллюзии глубины. Хотя экран по-прежнему двумерный и никаких реальных трехмерных кодов не используется, игрок тем не менее должен чувствовать, что дорога входит в экран, а не ползет по нему сверху вниз.
В дополнение мы примем небольшой набор правил. На дороге есть отметки, которых водителю необходимо коснуться, чтобы заработать очки. Чем быстрее водитель едет, тем большего числа потенциальных отметок он может коснуться, прежде чем закончится время игры. Но чем быстрее он едет, тем больше у него шансов не успеть поймать метку до того, как она уйдет. К тому же, если водитель дотронулся до границ дороги, он замедляет ход и уменьшает свою потенциальную возможность заработать очки, поскольку на меньшей скорости ему попадается меньше меток.
Другие возможности
Существует несколько способов сделать нашу игру более интересной. Цвета могут быть не произвольными, а обозначать определенное количество очков. Например, красные шары могут стоить 100 очков, синие - 50 и т.д. От цвета, в свою очередь, может зависеть скорость и высота полета шара. При этом чем выше и быстрее летит шар, тем больше его ценность.
Вы можете вообще отказаться от использования шаров. В сущности данная игра напоминает игры наподобие "Sea Wolf", задачей которых является поражение самолетов, или игры про космических пришельцев. Все, что требуется, - это заменить графику.
Как и предыдущую игру этой главы, только что рассмотренную можно усовершенствовать различными способами, например можно добавлять очки за шары, летящие выше и быстрее. Неплохим вариантом будет создание на ее основе игры, где в качестве целей будут использоваться самолеты. Оружие, из которого ведется обстрел, обычно в таких играх неподвижно, но может стрелять под разными углами.
Чтобы сделать игру труднее, вы можете ускорить движение захватчиков. Сначала попробуйте увеличить расстояние, на которое они падают каждый раз. Также можно увеличить скорость, с которой они движутся из стороны в сторону.
Если вы хотите добавить в игру уровней, то можете создать переменную startSpeed, которая начинается со значения 3. Задайте эту скорость функции balloonDirection каждого шарика вместо жестко заданного "3". Пусть теперь после того, как все шарики выбиты, игрок переходит к экрану "level over". Когда он нажимает кнопку "play next level", startSpeed увеличивается, и ролик отправляется к кадру "play", где шарики появляются с новой, более высокой скоростью.
К сведению
Нажатие клавиши пробела контролируется кнопкой. В нашем примере она расположена за пределами рабочего поля, в левом верхнем углу экрана и визуально представляет собой надпись "button". Кнопке назначен следующий код:
on (keyPress "") {
_root.shootBullet() ;
}
В соответствии с кодом кнопка не реагирует на щелчок мышью. В любом случае это не имеет значения, так как кнопка расположена за пределами рабочего поля. Программа ждет нажатия клавиши пробела и отвечает на него вызовом функции shootBullet.
На первый взгляд не ясно, почему используется клавиша пробела, а не проверка Key. isDown, осуществляемая функцией moveFox. Функция Key.isDown проверяет, нажата ли клавиша во время определенного промежутка времени. В нашем примере нажатие осуществляется один раз в каждом кадре. Если игрок быстро нажмет на клавишу, это событие может произойти между проверками Key. isDown. Программа не увидит, что клавиша нажата, и выстрела не произойдет. Использование кнопки гарантирует, что нажатие клавиши будет замечено и обработано.
Скорость воспроизведения ролика составляет 30 кадров в секунду, Благодаря этому анимация воспроизводится более плавно. Изменив скорость воспроизведения ролика, вам, может быть, придется изменить скорость перемещения лисы, шаров и снарядов. В противном случае скорость игры может не соответствовать вашим ожиданиям.
Так как пули в данной игре могут разлетаться в разные стороны, мы поменяли изображение пули в клипе, теперь она напоминает не короткую линию, а скорее небольшую точку.
Как и в исходной игре этой главы, здесь есть вводный и заключительный кадры. Я в обоих играх использую одинаковые кадры вне зависимости от того, выиграл игрок или проиграл. Вы можете сделать два разных кадра с соответствующим текстом в каждом.
Подготовка ролика
Основное отличие данной игры от предыдущей состоит в том, что соломинка представляет собой отдельный клип. Благодаря этому она может поворачиваться независимо от лисы. Клип лисы по сравнению с предыдущей игрой не содержит анимации движения. Он является ни чем иным, как элементом фона игры, хотя и расположен поверх клипа соломинки.
Как и в первой игре этой главы, есть кадр стоящей лисы - "stand", и анимация ходьбы. У шарика есть нормальный кадр и анимация взрыва. Все шарики сначала серого цвета и потом раскрашиваются с помощью ActionScript. Пуля - это короткий клип-линия.
В ролике Balloonshoot.fla клип лисы содержит кадр с меткой "stand" и анимационную последовательность, помеченную "walk". Анимация изображает лису, перемещающуюся влево (рис. 10.2), однако при помощи Action-Script вы можете повернуть лису в другую сторону, не создавая отдельной анимации. Главное условие: соломинка должна занимать во всех кадрах одно и то же положение относительно центральной точки клипа.

Рисунок 10.2 Лиса идет влево и всегда готова выстрелить из соломинки
Клип, соответствующий воздушному шару, также состоит из нескольких кадров. Первый кадр содержит изображение обычного шара. Остальные кадры воспроизводят анимацию лопающегося шара. Воспроизведение этой короткой анимации задается при попадании в шар. На рис. 10.3 показан единственный кадр анимации ролика, возможно, вы захотите изобразить взрыв более подробно.

Рисунок 10.3 При попадании в шар запускается воспроизведение анимации взрыва
Для окраски шара используются оттенки серого цвета. Цвет задается одновременно с созданием нового клипа шара. В результате один клип шара каждый раз принимает новый оттенок.
Клип снаряда содержит короткую линию. Хотя в качестве снаряда используется горошина, вертикальная линия создает видимость движения вверх.
Подход
Поведение лисы может остаться таким же, как в первой игре этой главы. Но поведение шариков должно быть полностью изменено. К тому же во время игры не должно быть создано ни одного нового шарика. Они все появляются в начале игры.
Для того чтобы соломинка была повернута в правильном направлении, прежде всего необходимо измерить горизонтальное и вертикальное расстояния между курсором и соломинкой, а затем с помощью этих значений вычислить необходимый угол.
Полученное значение можно использовать для поворота клипа coлoминки в нужном направлении. Оно также определяет место вылета снаряда и количество пикселов по горизонтали и вертикали, на которое снаряд перемещается в каждом кадре.
Добавить влияние гравитации немного проще. В начале движения объектата-пули его траектория слабо изменяется под действием гравитации. Однако с каждым кадром скорость падения увеличивается. Пуля получила сильный импульс при запуске, поэтому она будет продолжать двигаться вверх, но все медленнее и медленнее, по мере уменьшения ее кинетической энергии. Затем пуля все быстрее и быстрее начнет падать вниз.
Это явление называется ускорением свободного падения и в реальном мире составляет примерно 32 фута/с2 (9,8 м/с2). В мире игры ускорение может иметь любое значение.
Шарики-захватчики
Исходный файл: Ballooninvaders.fla
В самой классической видеоигре, "Космические захватчики", есть очень странное, но запоминающееся поведение вражеских единиц. Они движутся группой из стороны в сторону, медленно опускаясь вниз. Если они достигнут поверхности, игрок проигрывает.
Давайте изменим первую игру данной главы так, чтобы воздушные шарики вели себя как космические захватчики.
Создание кода
Небольшой клип "actions" помешается за пределами рабочего поля и контролирует процесс игры путем обращения к функциям главной временной шкалы. Она запускает игру при загрузке и вызывает ряд функций в каждом кадре.
onClipEvent(load) {
_root.initGame();
onClipEvent(enterFrame) {
_root.newBalloon() ;
_root.moveBalloons() ;
_root.moveFox();
_root.moveBullets();
}
Функция initGame задает все основные переменные, используемые в игре.
function initGame() {
// Инициализируем переменные, связанные с объектами-шарами.
nextBalloonTime = 0;
nextBalloon = 0;
balloons = [];
numBalloons = 10;
// Инициализируем переменные,
nextBulletTime = 0;
nextBullet = 0;
bullets = [];
// Количество очков равно 0.
score = 0;
}
Перед созданием нового шара необходимо провести три проверки. Первая определяет, остались ли в игре шары, вторая- прошло ли достаточно времени после создания предыдущего шара. Последняя проверка представляет собой своего рода игру "орел и решка": новый шар создается с вероятностью 50%.
После завершения проверок функция newBalloon создает новый шар с 50-процентной возможностью появления шара с левой или правой стороны. Скорость шара принимает произвольное значение от 3 до 5. Число является положительным, если шар будет пролетать слева направо и отрицательным в противном случае.
Цвет нового шара выбирается из пяти возможных оттенков. Для задания цвета используется функция setTransform.
Клипы шаров можно упорядочить, поместив их имена и значения скоростей в массив balloons.
Затем задаются переменные nextBalloon и nextBalloonTime, при помощи которых осуществляется обращение к переменной newBalloon.
function newBalloon () {
// Определяем, могут ли появиться новые шары,
if (nextBalloon < numBalloons) {
// Проверяем, пришло ли достаточно времени
// после появления последнего шара,
if (getTimerO > nextBalloonTime) {
// "Бросаем монетку",
if (Math.Random()
"balloon"+nextBalloon,
// Создаем новый шар.
Некоторые функции данной игры аналогичны функциям игры "Стрельба по воздушным шарам", поэтому нет смысла рассматривать их повторно. Это функции initGame, newBalloon, moveBalloons, checkCollision и distance.
Одна из новых функций в анализируемой игре - aimStraw. Она заменит функцию moveFox и будет вызываться из клипа "actions", которому назначен следующий код:
onClipEvent(load) {
root.initGame();
onClipEvent(enterFrame) {
_root.newBalloon ();
_root.moveBalloons() ;
_root.aimStraw();
_root.moveBullets() ;
}
Задача функции aimStraw - вычислить угол прицела и затем задать поворот клипа соломинки. Значение угла сохраняется в переменной strawRadians, которая используется функцией shootBullet. Для того чтобы вычислить угол между двумя точками, прежде всего необходимо определить значение разницы между горизонтальными и вертикальными координатами точек. Они хранятся в переменных dx и dy функции. Задав эти значения в функции Math.atan2, вы получите значение угла в радианах.
Углы измеряются в радианах или градусах. Полный круг в радианах будет равен 6,28 (2Pi), в градусах - 360. Радианы используются Flash в математических функциях наподобие Math.sin и Math.cos, а градусы - в параметрах клипов „rotation. Поэтому вы должны уметь преобразовывать значения из одних единиц измерения в другие.
Функция Math.atan2 является прекрасным инструментом для программирования игр. Арктангенс (во Flash - Math.atan) представляет собой функцию, вычисляющую угол наклона линии. Так как такой наклон определяется двумя точками, с помощью арктангенса можно преобразовать координаты этих точек в значение угла наклона. Однако при использовании арктангенса не учитывается, какая точка линии является анкером, а какая указателем, задающим угол. Поэтому легко получить углы, противоположные по значению тем, которые вам необходимы. Для того чтобы учесть различные варианты, необходимо написать несколько условных выражений. Функция Math.atan2 (y,x) вычисляет угол наклона линии между началом координат и точкой с координатами (х, у,). Тем самым решается проблема неоднозначности.
Клип "actions" такой же, как в первой игре этой главы, за исключением того, что новые шарики не создаются в каждом кадре.
onClipEvent(load) {
_root.initGame();
onClipEvent(enterFrame) {
_root.moveBalloons();
_root.moveFox();
_root.moveBullets();
}
Функция initGame вызывает функцию createBalloons, чтобы создать группу шариков. Ей не нужно задавать такие переменные, как nextBalloon или создавать массив balloons, поскольку после начала игры новые шарики не создаются.
function initGame() {
// Создаем шарики.
createBalloons О;
// Параметры снарядов.
nextBulletTime = 0;
nextBullet = 0;
bullets = [];
// Переменная счета.
score =0;
}
Функция createBalloons создает 30 шариков в 10 колонках по 3 штуки в каждой. Каждая ссылка на шарик хранится в массиве. Цвет шарику назначается в зависимости от того, в каком он ряду. Каждому шарику придано начальное направление и скорость равная 3.
function createBalloons() {
balloons = new Array();
balloonNum = 0;
// Создаем новый ряд.
forfvar y=0;y
for(var x=0;x
// Создаем и размещаем новый шарик.
attachMovie("balloon", "balloon"+balloonNum, balloonNum) ;
balloonClip = this["balloon"+balloonNum];
balloonClip._x = x*30+20;
balloonClip._y = y*30+20;
// Добавляем в массив,
balloons, push (balloonClip) ;
// Устанавливаем цвет.
balloonColor = new Color(balloonClip);
if (y == 0) {
balloonColor.setTransform({rb: 255});
} else if (y == 1) {
balloonColor.setTransform({gb: 255});
} else if (y == 2) {
balloonColor.setTransform({bb: 255});
balloonNum++;}
}
// Направление (скорость) шариков.
balloonDirection = 3;
}
Функция moveBalloons двигает все шарики в массиве balloons. Если какой-нибудь из них дотронется до края экрана, то все они меняют направление. Если же какой-нибудь достигнет низа экрана, игра заканчивается.
function moveBalloons() {
// Переменная-флаг изменения направления,
var newDirection = false;
// Просматриваем все шарики,
for(var i=0;i
// Передвигаем текущий шарик,
Стрельба по воздушным шарам
Исходный файл: Balloonshoot.fla
Первая игра состоит из трех основных элементов: лисы, воздушных шаров и снарядов. В нашем примере лиса стреляет всего лишь горошинами из соломинки (рис. 10.1). Поэтому игра подойдет для любой аудитории.

Рисунок 10.1 Лиса стреляет по пролетающим воздушным шарам из соломинки
удалить из предыдущей игры один
Наша задача - удалить из предыдущей игры один элемент и добавить два новых. Элементом, который необходимо удалить, является перемещение лисы вправо и влево. В данной игре клавиши со стрелками "влево" и "вправо" действовать не будут, а лиса будет оставаться в центре экрана.
Новые элементы - возможность прицеливаться и подчинение пули закону гравитации. При помощи мыши игрок может прицелиться, и соломинка повернется в нужном направлении. После выстрела пуля упадет на землю.
Задача этого проекта - создать игру, в которой лиса перемещается влево и вправо и стреляет вверх по воздушным шарам. Шары появляются слева и справа, на разной высоте и летят с разной скоростью. После того как пролетит определенное количество шаров, игра заканчивается. Счет определяется количеством лопнувших шаров. Готовую игру можно просмотреть в файле Balloonshoot.fla.
Поведение шариков простое. Они образуют
Поведение шариков простое. Они образуют группу шириной 10 и высотой 3 шарика, как показано на рис. 10.5. Шарики движутся вправо, пока первая колонна шариков не коснется правой стороны экрана. Тогда они меняют направление и чуть-чуть опускаются.

Рис 10.5 Шарики-захватчики движутся группой
Между тем лиса внизу движется слева направо и стреляет в шарики. Она должна перестрелять их всех, прежде чем группа шариков достигнет поверхности земли.
Бита и блоки: три измерения
Исходный файл: 3Dpaddlebricks.fla
Итак, в этой главе вы видели, как шар движется по плоскости. А что если шар должен будет двигаться в третьем измерении: в глубину? На рис. 11.5 показано, как это может выглядеть. Бита - это полупрозрачный квадрат на переднем плане игры. Четыре боковые стены ведут к задней стене, находящейся на некотором расстоянии "в глубине" экрана. Шар уменьшается по мере того, как становится все дальше от биты. Цель состоит в том, чтобы выбить все кирпичи (блоки) из задней стены.

Рисунок 11.5 Цель этой игры такая же, как и у предыдущей, но перспектива создает некоторую специфичность
Бита и блоки
Исходный файл: Paddlebricks.fla
Следующая игра намного сложнее двух предыдущих, хотя в ней используются те же основные элементы: мяч, бита и стены. Это классическая игра изначально называлась "Breakout". На рис. 11.4 показан фрагмент игры. В дополнение к мячу и бите вверху экрана расположены пять рядов блоков. Цель игры - выбить блоки с помощью мяча. Когда будут выбиты все блоки, игра переходит на следующий уровень, где мяч летит с большей скоростью.

Рисунок 11.4 В игре "Бита и блоки" представлены ряды блоков, которые игрок должен выбить с помощью мяча
Другие возможности
Игру можно усовершенствовавать, если позволить игроку пропустить в течение игры определенное количество мячей. Таким образом, игра не будет заканчиваться после пропуска первого мяча, а продолжится со вторым мячом и т.д.
Осуществить это можно, присвоив, например, в начале игры переменной ballNum значение 3 или какое-либо другое. В результате, если велична ballNvun будет превышать 0, вместо кадра "game over" ролик будет переходить к кадру "ball lost". Игрок может нажать любую клавишу и начать игру заново, но при этом значение ballNum
Изменить количество мячей просто: достаточно изменить только одно значение в кадре "start game". Изменяя другие параметры, можно продлить или усложнить игру. Есть и другие варианты усовершенствования игры - например, увеличить скорость биты компьютера, поменяв одно значение в функции moveComputerPaddle.
Также можно сделать компьютер "умнее". Например, написать код, который будет предугадывать место, куда прилетит мяч, и передвигать туда биту вместо того, чтобы просто перемешать ее вслед за мячом. При пересечении границ игрового поля мяч будет ударяться о верхнюю или нижнюю стенку только один раз, так что определить предполагаемое место можно с помощью простых математических расчетов, если вы хорошо владеете математикой.
Игра станет интереснее, если в ней будет подсчет очков. Здесь это не сделано для того, чтобы не усложнять код. Просто добавьте текстовое поле "score" и свяжите его с переменной score. Затем прибавляйте единицу каждый раз, когда игрок выбивает блок.
Возможно, вам также захочется добавить текстовые поля, чтобы сообщать пользователю, на каком он уровне и сколько осталось мячей. Можно добавить и звуковые эффекты.
Очень простой способ внести дополнение в эту игру - поместить какой-либо рисунок за блоками. Это можно сделать вообще без использования ActionScript. Можно также сделать, чтобы в конце каждого уровня пользователь видел другую картинку.
К сведению
Убедитесь, что экземпляру клипа с мячом присвоено имя "ball", а экземпляру клипа с битой - "paddle". Если стены расположены не так, как в исходном ролике, проверьте, правильно ли указаны константы в функции initGame.
В основной кадр игры необходимо включить оператор stop, чтобы вставить паузу в основную временную шкалу (это поможет избежать досрочного перехода к кадру окончания игры).
В дополнение к уже описанным элементам необходимо создать текстовые поля playerScore и computerScore и поместить их на рабочее поле. Они должны быть расположены во всех кадрах, кроме "start game", таким образом, чтобы были видны между подачами мяча и в конце игры.
Для работы кода необходимо точно указать множество элементов. Запустите ролик Paddlebricks.fla, чтобы посмотреть готовый вариант программы в действии. Для создания своей собственной версии необходимо запомнить имена всех клипов и в каждый кадр вставить команду stop. Также нужно вставить небольшие фрагменты кода в кнопки и первый кадр.
Ряды блоков были раскрашены с помощью эффекта Tint (Окраска), благодаря чему игра стала визуально более интересной. Вы можете выбрать другое графическое решение, ничего не меняя в функциональной части игры.
Игра, в общем то, лишь приблизительно воспроизводит трехмерный мир. Например, когда мяч отлетает в угол, компонент скорости z меняется таким образом, что суммарный вектор скорости остается неизменным Вы можете попробовать спрятать курсор перед началом игры с помощью Mouse.hide (), только не забудьте вернуть его на место по окончании игры с помощью Mouse. show ().
Подготовка ролика
Единственными фафическими объектами, необходимыми для этой игры являются мяч, бита и стены. Изображения стен не используются в коде, так как реальные фаницы ифового поля определяются с помощью значений определеннных констант.
Для этого ролика нужно пять кадров, то есть больше, чем в ранее рассмотренных играх. Первый кадр - "start game". Он появляется только в начале игры. Щелчок по кнопке Play переводит игрока непосредственно в кадр "play", и игра начинается.
Второй кадр - это "start level". Он отображается, когда игрок переходит на второй и последующие уровни. Здесь щелчок по кнопке Play также переносит игрока в кадр "play", то есть к началу нового уровня.
Третий кадр - "start ball". Он отображается, когда игрок пропускает мяч и хочет подать себе следующий. Внимательно рассмотрите исходный файл. Как видите, блоки присутствуют в третьем и четвертом кадрах, то есть в кадре "play". Таким образом, изображения блоков сохраняются, пока ролик переходит от кадра "play" к кадру "start ball". Иначе блоки будут расположены на своих исходных позициях.
Последний кадр - "game over". Щелчок по кнопке Play перенесет игрока обратно к кадру "start game", где значения некоторых важных параметров будут восстановлены.
Кроме организации расположения кадров необходимо создать блоки для третьего и четвертого кадров. В исходном ролике блоки имеют ширину 48 пикселов и высоту 8 пикселов. В примере расстояние между ними составляет 50x10 пикселов, таким образом, получается 5 рядов блоков по 11 блоков в каждом, что в общей сложности составляет 55 блоков.
Для того чтобы не именовать 55 блоков на рабочем поле, подумайте, а не начать ли игру вовсе без блоков, а затем воспользоваться оператором attachMovie, чтобы добавить каждый блок с помощью кода. Хотя данная техника здесь не применяется, можно посмотреть, как она реализована в следующей игре этой главы.
К сожалению, каждому блоку должно быть присвоено имя, чтобы код мог его распознать. В исходном файле им назначены имена от al до а55. Клип с мячом называется "ball", а с битой - "paddle".
Ролик включает в себя четыре кадра. Все действия происходят во втором кадре. Фоном для всех кадров служит параллелепипед, показанный на рис. 11.5. Его внешняя граница размером 400x400 полностью заполняет рабочее поле. Внутренняя граница, представляющая заднюю грань, имеет размер 120x120 и располагается точно в центре.

Рис.11.6 Обозначены значения х, у и z каждого угла игровой области
Остальные клипы также находятся на экране. Первый - это бита, квадрат размером 70x70. Этому клипу присвоено имя "paddle" и его параметр _alpha=50%, что делает его полупрозрачным. Мяч - это клип "ball", содержащий круг диаметром 30 пикселов. Также в стороне расположен клип "action".
В библиотеке есть также клип "brick". Клип экспортируется вместе с роликом. Он используется для создания кирпичей, которые покрывают заднюю стену.
Если вы внимательно посмотрите на рисунок 11.5, то кроме толстых линий наружной и внутренней стен можете увидеть контур из тонких линий где-то в середине. Этот набор линий движется вместе с мячом вглубь экрана. Он помогает игроку определить, где находится мяч. Посмотрите ролик-пример, чтобы увидеть, как это работает. Вам нужен, клип размером 400x400, чтобы сделать эти линии. В примере этот клип называется "ring".
В общих чертах ролик аналогичен предыдущему. Вместо трех кадров вам понадобятся четыре: "start game", "start level", "play" и "game over". Перед каждой подачей мяча будет виден кадр "start level". Кадр же “game over" станет отображаться только тогда, когда будет пропущен последний мяч.
Как и в предыдущей игре, вам нужен один клип под названием "paddle» и еше один с именем "computerPaddle". Поведение второй биты будет запрограммировано с помощью языка ActionScript. Так как бита компьютера будет располагаться справа, необходимо убрать правую стенку. При этом верхняя и нижняя стены останутся.
Подход
Самое сложное при создании этой игры - сделать так, чтобы мяч правильно отскакивал от стен. Многие программисты не учитывают ни диаметр мяча, ни его скорость. В результате может случиться, что мяч будет отскакивать не от стены, а от точки, расположенной за ней.
Рассмотрим ситуацию, когда мяч оказывается за стеной. При этом надо выяснить, насколько далеко залетел мяч за пределы игрового поля. Так как мяч перемещается на несколько пикселов в одном кадре, он может легко проскочить за стену на несколько пикселов.
После того как вы узнаете, насколько далеко за стеной оказался мяч, вы можете изменить направление его движения, а затем поместить мяч на соответствующее расстояние с нужной стороны стены. На рис. 11.2 показана диаграмма работы данного алгоритма.

Рисунок 14.2. Диаграмма показывает, как изменяется положение мяча после столкновения со стеной
Столкновения с битой рассматриваются точно так же, как и столкновения со стеной. Единственное различие - вы должны изначально убедиться, что вертикальное положение биты допускает удар мяча об нее.
Если мяч проходит через горизонтальное положение биты, но ее там нет, нужно присвоить некой переменной значение, указывающее, что мяч был пропущен. Таким образом, у пользователя не будет другого шанса отбить мяч, пока тот летит до границы экрана.
Искусственный интеллект для этой игры можно создать разными способами. Один из них - сделать так, чтобы бита всегда следовала за мячом. Однако в этом случае у компьютера просто не будет возможности пропустить мяч.
Лучше, если бита компьютера будет медленно двигаться в направлении мяча. Если мяч будет лететь слишком быстро, компьютер может не успеть переместить биту в правильное положение. Кроме того, бита будет двигаться только тогда, когда мяч летит в искусственного противника.
Словосочетание "искусственный интеллект" звучит таинственно. Однако для игр не так важно, чтобы противник был умным. Компьютер должен только способствовать захватывающей игре. Конечно, в большинстве игр гораздо проще создать безупречного противника. Однако в таком случае игра для компьютера становится беспроигрышной, что не интересно для игрока. Трудность состоит в том, чтобы создать противника, обладающего некими навыками (это сделает игру непростой), но чтобы имеющихся навыков не хватало для беспроигрышной игры.
Для того чтобы счет игры был сохранен, нужны несколько переменных. Однако создать паузу в игре между подачами мяча довольно сложно, поэтому в игре будет два кадра: в первом программа ждет, когда игрок щелкнет по кнопке "serve", а во втором разворачивается само действие игры. Этот второй кадр начинается с установки произвольного начального положения мяча.
Код для определения, в каком месте биты или стены ударился мяч, похож на код предыдущих двух игр. Единственное отличие заключается в том, что теперь мяч может отскакивать не только от верхней биты, а и от любой ее точки. Таким образом, становится немного проще отбить мяч.
При столкновении мяча с блоком направление его движения по вертикали изменяется на противоположное. Блок же удаляется с экрана.
В предыдущих играх было достаточно определить, когда мяч ударяется о блок, для чего использовался метод hitTest. Теперь задача усложняется: надо рассмотреть все четыре стороны мяча по отношению ко всем четырем сторонам блока. Если мяч и блок полностью перекрываются, то считается, что произошло столкновение. С помощью метода hitTest можно было бы определить момент, когда мяч находится внутри прямоугольного блока. Но этого не достаточно для данной игры.
При столкновении мяча с битой рассчитывается расстояние между центром мяча и центром биты. Длина биты - 50 пикселов, так что это расстояние может быть чуть более 25 пикселов, либо со знаком "+", либо со знаком "-". Разделите данное число на 4 и получите значение между -7 и 7.
Новое значение будет присвоено переменной dx, которая определяет скорость движения мяча по горизонтали.
Это значит, что игрок может направлять мяч. Если, например, он отобьет мяч левым краем биты, мяч будет направлен резко влево. Если же отбить серединой биты, то мяч полетит прямо вверх.
Чтобы следить за положением мяча, необходима новая переменная. Можно использовать х для горизонтальной и у для вертикальной характеристики положения шара. Третья переменная, z, следит за глубиной -как глубоко внутри экрана находится шар.
Эти три переменные определяют положение мяча внутри воображаемого параллелепипеда, в котором происходит игра. Этот параллелепипед имеет горизонтальные и вертикальные размеры по 400 единиц и 140 единиц в глубину. Чтобы перевести это в координаты экрана, нужна некоторая ловкость. Если вы еще раз посмотрите на рис. 11.5, то заметите, что границы шахты видимы. Наружный квадрат (грань), ближний к игроку, находится на том же уровне, что и бита. Он имеет размер 400x400. Внутренняя грань, представляющая заднюю стену, имеет размер 120x120.
На рисунке 11.6 еще раз изображены обе грани, но на этот раз с обозначенными х, у и z координатами. Верхний левый угол обеих граней имеет значения х и у равные 0. Однако наружный угол имеет значение z равное 0, а внутренний - значение z, равное 140. Остальные углы обозначаются аналогично.
Если мяч находится на позиции (х, у) = (0,0) и движется от 0 к 140 вдоль оси Oz, то он движется вдоль ребра параллелепипеда (рис. 11.6). Если мяч в центре экрана, в положении (200,200), и движется от 0 до 140 вдоль Oz, ему вообще не нужно смешаться вправо или влево. Если мяч в какой-нибудь промежуточной позиции, например (50,65), и движется от 0 до 140 вдоль Oz, то он должен двигаться вдоль своей линии перспективы так, чтобы сохранить свое положение относительно передней и задней граней.
Иллюзия трехмерности достигается также за счет уменьшения значения масштаба мяча по мере его удаления.
Создание кода
Для этой игры необходимы лишь три функции (посмотрите исходный файл, Wallball.fla). Все эти три функции будут вызываться в клипе "actions”:
onClipEevent(load) {
_root.initGame();
}
onClipEvent(enterFrame) {
_root.moveBall();
_root.movePaddle () ;
}
Функции находятся в основной временной шкале. Первая функция, initGame, хранит положение мяча в переменных х и у. Указаны значения dx и dy, то есть скорость мяча по вертикали и горизонтали (5 пикселов в кадре каждая). Затем функция initGame устанавливает несколько постоянных, определяющих положение каждой стены. Этой функции передается значение радиуса мяча, которое также используется функцией moveBall. Переменной passedPaddle присваивается значение true после того, как ифок пропустит мяч. При этом надо спрятать курсор, чтобы он не отвлекал внимание игрока.
function initGame() {
// Устанавливаем начальное положение мяча,
х = Ьа11._х;
у = ball._y;
// Указываем начальную скорость,
dx = 5;
dy = 5;
// Устанавливаем значения постоянных.
rightwali = 550;
leftWall = 0;
topWall = 0;
bottomWall = 4 4 0;
ballRadius = ball._width/2 passedPaddle = false;
// Прячем курсор.
Mouse.hide();
}
Функция movePaddle - "рабочая лошадка" этой игры. Сначала она изменяет значение х и у на величину значений dx и dy соответственно, чтобы получить новое положение мяча (1). Затем проверяет, пролетел ли мяч сквозь стену или нет (2).
К радиусу мяча прибавляется значение его положения, чтобы получить точную позицию правого края мяча. Если мяч оказался за стеной, функция movePaddle подсчитывает, как далеко он перелетел, и присваивает это значение переменной overshoot. Затем мяч перемешается назад на расстояние, в два раза превышающее значение overshoot. Направление мяча меняется при умножении dx на -1, таким образом, знак dx меняется на противоположный. Если значение dx до столкновения мяча со стеной было равно 5, то после этого события становится равным -5.
Затем код проверяет, пролетел ли мяч сквозь нижнюю стену или нет (3). Этот фрагмент похож на предыдущий, только вместо х и dx используются величины у и dy.
Фрагмент кода, где проверяется, пролетел ли мяч через верхнюю стену, несколько отличается от уже рассмотренных (4). Для определения положения верхней границы мяча из положения его центра вычитается радиус. Затем величина overshoot рассчитывается как разница между положениями стены и верхней границы мяча.
Для того чтобы определить, ударился ли мяч о биту или нет, сначала код рассчитывает положение правой границы биты (5). Потом, если мяч находится достаточно близко к бите, рассчитываются верхняя и нижняя границы, а затем определяется, пересекаются ли мяч и бита (6).
Если мяч сталкивается с битой, то он ведет себя так же, как и при столкновении со стеной. Однако при этом скорость мяча увеличивается на 5% (7). Если мяч перелетает через стену, совершается только одно действие - переменной passedPaddle присваивается значение true.
Если значение переменной passedPaddle равно true, и мяч находится там, где должна быть левая стена, игра заканчивается (8). Курсор возвращается в исходное положение, и ролик переходит к кадру "game over".
В конце функции moveBall положение мяча устанавливается в соответствии со значениями х и у.
Прежде чем будет запушен кадр игры, в кадре "start game" необходимо определить две важные переменные: начальную скорость движения мяча по вертикали и количество мячей, которые могут быть поданы.
dy = 3;
numBalls = 3;
stop() ;
Когда происходит переход к кадру "play", с помощью клипа "actions» можно регулярно вызывать функции. В данной игре все столкновения с мячом или стенами должны быть учтены в функции moveBall, но для блоков была создана отдельная функция - checkCollisions.
onClipEvent(load) {
_root.startBall();
onClipEvent(enterFrame) {
_root.moveBall();
_root.movePaddle();
_root.checkCollisions();
}
Когда начинается кадр "play", подается мяч. Положение мяча определяется тем, где он появляется на рабочем поле. Скорость мяча по горизонтали всегда равна 3, направление движения - вправо. Скорость по вертикали указывается в первом кадре, где величине dy было присвоено значение 3. Однако это значение изменится перед следующим уровнем.
Вдобавок к параметрам мяча воспользуйтесь возможностью и установите некоторые значения, которые не будут изменяться во время игры.
function startBall() {
// Определяем начальное положение мяча,
х = ball._x;
у = ball._y;
// Устанавливаем начальную скорость по горизонтали,
dx = 3;
// Прячем курсор.
Mouse.hide();
// Задаем значения констант.
rightWall = 550;
leftWall = 0;
topWall = 0;
bottomWall = 400;
ballRadius = ball,_width/2;
paddleTop = paddle._y-paddle._height/2;
paddleBottom = paddle._y+paddle.__height/2;
}
Следующая функция управляет битой, выравнивая ее по горизонтали в соответствии с движением мыши.
// Бита следует за курсором,
function movePaddle() {
paddle._x = _xmouse;
}
Следующая функция покажется вам знакомой, так как она очень похожа на функцию moveBall, которая используется в других играх этой главы. Однако есть и некоторые отличия.
Для того чтобы узнать, ударился ли мяч о биту, код проверяет, полностью ли они перекрываются (13). Затем, если все-таки столкновение произошло, скорость мяча по горизонтали определяется тем, где именно мяч ударился о биту (14). К тому же код для определения, пропущен ли мяч, проще, так как он просто проверяет, пролетел ли мяч сквозь нижнюю стену или нет (15).
Код состоит в основном из функций, расположенных во втором кадре. Первая начинает игру. Вместо отдельных переменных для хранения х, у и z значений мяча, мы используем один объект, ballpos, который имеет о свойства. Таким образом, ballpos .x соответствует x-положению мяча. То же самое мы делаем для ballvel, где содержатся х, у и z скорости мяча.
В начале игры значения свойств объекта bollpos устанавливаются таким образом, чтобы мяч начинал свое движение от задней стенки параллелепипеда. Значения объекта ballvel задают начальное движение мяча строго вдоль оси Oz и скорость на единицу большую номера уровня игры (то есть 2).
Следующая часть функции initGame создает 16 блоков из одного библиотечного образца и покрывает ими всю заднюю стенку. В заключении функции мы устанавливаем уровень биты и шара так, чтобы они были расположены поверх созданных кирпичей.
function initGame() {
// Устанавливаем мяч.
ballpos = {х:200, у:200, z:140};
// Определяем его скорость.
ballvel = {х:0, у:0, z:-(1+gameLevel)};
// Создаем блоки,
bricks = new Array();
for(var x=0;x
for(var y=0;y
brick = attachMovie("brick","brick"+x+y,x+y*4);
brick._x = 155+30*x;
brick._y = 155+30*y;
bricks.push(brick);
// Перемещаем биту и шар на передний план.
paddle.swapDepths(101);
ball.swapDepths(100);
}
Клип "actions" вызывает всего две функции.
onClipEvent(enterFrame) {
_root.movePaddle();
_root.moveBall(); }
Первая из этих функций, movePaddle, очень простая. Она устанавливает биту в позицию курсора.
function movPaddle() {
//Положение биты соответствует положению курсора.
Paddle._x=_root._xmouse;
Paddle._y=_root._ymouse;
}
А вот функция moveBall выполняет очень много действий. Вначале переопределяются координаты мяча (объект ballpos) с помощью значений объекта ballvel (16).
Затем вычисляется положение мяча на экране (17). Координата х определяется как значение ballpos. х, подкорректированное в соответствии со значением ballpos.z. Чем глубже находится шар, тем большую величину составляет поправка. Второй множитель поправки определяется тем, насколько далеко находится шар от стенок колодца. Если, например, шар находится ровно посередине между стенкой и центральной осью, то есть ballpos.х = 100 или (-100), то поправка будет равняться значению ballpos.z (ballpos.z соответственно). Если вы не вполне поняли логику этих рассуждений, попробуйте поменять различные параметры объекта bollpos и посмотрите на результат.
Следующий фрагмент кода устанавливает значение масштаба шара в соответствие со значением ballpos.z (18). Поскольку максимальное значение ballpos.z составляет 140, то минимальный масштаб составляет (200-140)/2, то есть 35%.
Далее мы устанавливаем масштаб клипа "ring" (19). Этот клип выполняет роль указателя, помогающего понять, на какой глубине находится шар в данный момент.
Если шар сталкивается с одной из стен параллелепипеда (20), происходит отражение от стенки. Проверка выполняется для всех четырех стен.
Столкновение с задней стенкой (21) обрабатывается несколько сложнее. Значение z меняется на противоположное. Кроме того, клипы блоков проверяют, куда именно врезался шар. Блок, с которым произошло столкновение, удаляется, и счет увеличивается.
Передней стенки у нас нет, но на ее месте располагается бита. Если параметр z принимает значение 0, клип биты проверяет, попал ли в него? шар (22). Бита имеет размер 70x70, так что шар должен находиться не далее чем в 35 пикселях по каждой из координат от центра биты. При столкновении определяются новые значения скорости шара в соответствии с расстоянием от центра биты до места столкновения (23). При столкновении строго по центру шар отражается отвесно, тогда как отражение, например, от левой стороны отклоняет мяч влево и т.д.
При столкновении с битой ее параметр _alpha на мгновение принимает значение 90 (24). В следующем кадре значение восстанавливается (26).
Если шар пролетает мимо биты, игра заканчивается (25). Если же все блоки оказываются выбиты, игрок переходит на следующий уровень.
В сценарий предыдущего ролика необходимо внести некоторые изменения. Изменить существующие функции и добавить одну новую. Приведем сценарий клипа "actions", который вызывает новую функцию moveComputerPaddle:
onClipEvent(load) {
_root.startLevel();
}
onClipEvent(enterFrame) {
_root.moveBall ();
_root.movePaddle() ;
_root.moveComputerPaddle();
}
Вместо функции startGame в этой игре используется функция startLevel, которая обладает всеми возможностями функции startGame и в дополнение к ним указывает, что мяч будет двигаться в произвольном направлении. Достичь этого можно, определив, что мяч в 50% случаев подается вверх, в 50% случаев - вниз, также в 50% случаев - влево и в 50% случаев - вправо. То есть вы получаете четыре возможных направления движения мяча по диагонали.
function startLevel() {
// Определяем начальное положение мяча,
х = ball._x;
у = ball._y;
// Указываем начальную скорость и одно из четырех
// произвольных направлений по диагонали,
dx = 5;
dy = 5;
if (Math.random() < .5) dx *= -1;
if (Math.random() < .5) dy *= -1;
// Прячем курсор. Mouse.hide();
// Устанавливаем значения констант.
rightWall = 550;
leftWall = 0;
topWall = 0;
bottomWall = 400;
ballRadius = ball._width/2;
passedPaddle = false;
}
Теперь в функцию moveBall включен код для определения, пролетел ли мяч мимо биты компьютера или нет (10). Он похож на код, обрабатывающий биту игрока (9), и идентичен соответствующему фрагменту кода предыдущей игры.
Когда мяч пролетает с правой (11) или с левой (12) стороны, обычно игра возвращается к кадру "start level". Однако если не осталось больше мячей, программа переходит к кадру завершения игры, "game over". В зависимости от того, кто пропустил мяч, очко записывается либо игроку, либо компьютеру (переменной playerScore или computerScore).
function moveBall() {
// Изменяем координаты х и у.
х += dx;
y += dy;
// Проверяем, попал ли мяч в нижнюю стену,
if (y+ballRadius > bottomWall) {
Стена и мяч
Исходный файл: Wallball.fla
Первая игра называется "Стена и мяч". В ней имеются бита, управляемая пользователем, и три стены, от которых может отскакивать мяч. Четвертой стены нет (она открыта). Задача игрока состоит в том, чтобы не позволить мячу пролететь мимо биты (рис. 11.1).

Рисунок 11.1 Элементами игры "Стена и мяч" являются мяч, бита и три стены
создать игру, где двигающийся мяч
Цель данного проекта – создать игру, где двигающийся мяч будет отскакивать от стен и биты. Бита будет перемещаться по вертикали в соответствии с движением мыши. Если мяч пролетает мимо биты и достигает границы экрана, игра заканчивается. При столкновении мяча с битой скорость первого должна немного увеличиваться.
Цель игры состоит в том, чтобы создать противника, обладающего искусственным интеллектом, с которым будет соревноваться игрок. Левая бита будет управляться игроком, а правая - воссоздавать возможную реакцию человека с помощью компьютерных расчетов.
Мяч будет отскакивать от верхней и нижней стен, и только от действий игрока и компьютера будет зависеть, вылетит ли он за пределы экрана.
Когда мяч пролетает мимо одной из бит игроков, игра приостанавливается до тех пор, пока пользователь не щелкнет по кнопке "serve". Затем мяч снова появится в середине экрана. Счет игры сохранится. Игра заканчивается в том случае, если один из игроков наберет 7 очков.
Цель состоит в том, чтобы создать классическую игру игровых автоматов с битой и блоками. С помощью мыши можно перемешать биту по горизонтали. Мяч отскакивает от верхней и боковых стен и считается пропущенным, если пролетает мимо биты, сквозь нижнюю стену.
Когда мяч ударяется о блок, он отскакивает, а блок исчезает. После того как будут выбиты все блоки, игра переходит на другой уровень, где на экране окажутся те же блоки, но мяч будет двигаться быстрее. Просмотрите ролик Paddlebricks.fla, чтобы увидеть, как работает игра.
Другое отличие этой игры от предыдущих состоит в том, что направление движения мяча зависит от того, в каком месте мяч ударится о биту. Если он попадает в левую часть биты, то отлетает влево, если же в правую, то вправо. Угол определяется тем, насколько далеко от центра биты ударился мяч.
Задача этой игры - создание иллюзии трехмерности. Экраны компьютеров безнадежно завязли в двух измерениях. Но изменяя размер шара: и используя линии перспективы, чтобы заставить шар двигаться по мере удаления по направлению к центру экрана, вы можете создать иллюзию, что шарик движется прямо вглубь экрана.
Цель состоит в том, чтобы выбить все 16 блоков из задней стены. Как только шар касается кирпича, он выпадает. Когда шар достигает уровня с битой, она должны занимать такое положение, чтобы коснуться мяча. Место, где шар коснулся биты, определяет новое направление шара.
Когда все 16 кирпичей выбиты, уровень пройден. На следующем уровне шар движется несколько быстрее.
Другие возможности
Хотя цель игры заключается в отображении только 10 вопросов, ни одна строчка кода не ограничивает их число. Можно запросить большее или меньшее количество вопросов из файла Flashquiz.txt.
Вместе с выводом строки пользователю можно показывать некое сообщение. Например, при отображении строчки "8 out of 10" можно подбодрить пользователя следующим образом: "You know your planets!" (Вы знаете планеты!), а при двух не правильных ответах из 10 будет выводиться сообщение "Go back to school" (Снова идите в школу).
Как и в предыдущей игре, в текстовый файл можно поместить столько вопросов, сколько вы хотите. Если вы знакомы с программированием CGI, вы даже можете написать программу для сервера, которая будет генерировать файл Flashtrivia.txt на основе базы данных вопросов.
Вы также можете изменить начальное количество очков для вопросов, а также число очков, вычитаемых за неправильный ответ.
В этом примере фраза жестко запрограммирована в функции initGame. Однако можно загружать текст из внешних источников (как это сделать. вы узнали из предыдущих разделов этой главы), так будет проще изменять фразу. Вы даже можете использовать список фраз, которые будут отображаться одна за другой или в случайном порядке.
Если вы хотите включить в игру знаки пунктуации, следует изменить код, чтобы в начале игры кроме пробелов программа автоматически отображала и эти знаки. С помощью функции isAlpha можно проверить, является ли символ буквой, и если нет, то сразу его показать.
По мере того, как игрок движется вдоль фразы с помощью клавиш со стрелками, курсор иногда оказывается над пробелом или другим неактивным знаком. Вы можете расширить код, чтобы следить за движением курсора и, когда он находится на пустым пространством, заставить его продолжать движение вперед или назад, пока он не коснется буквы.
Хотя исходный ролик содержит фразу, встроенную в код, вы можете считывать ее с помощью команд LoadVariables или LoadVars. Это дает вам возможность изменять фразу без перекомпилирования swf-файла.
Игра "Виселица"
Исходный файл: Hangman.fla
Следующая игра должна быть знакома всем. В классической игре с ручкой и бумагой, "Виселице", игрок должен угадать, какие символы используются в фразе. Если он угадывает букву, становятся видны все места ее включения во фразу. Если во всей фразе нет такой буквы, добавляется фрагмент рисунка с повешенным человеком. Если рисунок закончен прежде, чем фраза угадана, игрок проигрывает.
К сведению
Вам понадобятся два звука, один с именем "right", а другой - "wrong". Также потребуется кнопка "continue", похожая на изображенную на рис. 12.3. Если у вас есть вопросы по работе программы, просмотрите ролик Flashquiz.fla.
Внимательно просмотрите каждый элемент ролика Flashtrivia.fla. В нем находятся текстовые поля: для вопроса, четырех ответов, количества возможных очков и счета. Каждая кнопка представляет собой копию одного и того же клипа, вверху нее расположен статический символ. Эти символы лишь напоминают пользователю, что он может нажать соответствующую клавишу на клавиатуре вместо того, чтобы щелкнуть по самой кнопке.
В конце ролика нужно вставить кадры "win" и "lose", к которым игра будет переходить при ее завершении. В ролике Hangman.fla эти кадры статичные, но вы можете добавить какую-либо анимацию в любой из них. Например, анимация "win" может показывать, что лису отпускают, в то время как анимация "lose" может демонстрировать что-нибудь устрашающее.
Исходный ролик содержит кадр "game over". Это к нему возвращается ролик, когда головоломка решена. Вы также можете использовать removeListener, если хотите заставить ролик перестать отвечать на нажатие клавиш.
Криптограмма
Исходный файл: Cryptogram.fla
Криптограмма - это довольно распространенный вариант головоломки из слов, которая зачастую бывает труднее, чем игра в виселицу. Если вы никогда не видели ничего подобного, загляните в раздел кроссвордов в вашей местной газете. Скорее всего, рядом с ежедневным кроссвордом вы найдете и криптограмму.
В криптограмме предложение или высказывание зашифровано с помощью самой простой технологии: каждая буква алфавита заменена какой-нибудь другой буквой. Например, "Привет" может быть "Бнефид", где Б заменяет П, Н заменяет Р, Е заменяет И, Ф заменяет В, И заменяет Е и Д заменяет Т.
Странность криптограмм в том, что чем они длиннее, тем легче их расшифровать. Обычно процесс начинают с поиска слов, состоящих из одной буквы, они могут значить «и» и «в», двухбуквенных слов, часто это «на», «по». Если фраза начинается с трехбуквенного слова, это может быть «что».
Подготовка ролика
В этом ролике четыре кадра. Первый загружает вопросы и ответы и помещает их в массив. Второй кадр содержит информацию о правилах игры.
В третьем кадре начинается само действие, отображается вопрос, четыре ответа, кнопка рядом с каждым ответом, количество возможных очков и счет, оба последних текстовых поля - динамические, первое связано с переменной potentialPoints, а второе - с переменной score.
Помните, что на самом деле четыре ответа - это клипы, в которых находятся текстовые поля, отображающие содержимое переменной text. Однако имена четырех клипов отличаются цифрой: от "answer0" до "answer3".
И последний кадр игры - "game over". В нем показывается окончательный счет, и пользователь может щелкнуть по кнопке, чтобы сыграть заново.
Основной элемент - текстовое поле на экране. Сначала в нем находятся только пробелы и знаки подчеркивания, которые постепенно меняются на буквы, угадываемые игроком.
Текстовое поле должно быть динамическим и связано с переменной display. В панели Properties необходимо также выставить свойство Miltiline для текстового поля.
Текст отображается моноширинным шрифтом Monaco, который имеется в стандартной поставке системы Macintosh. Если вы создаете ролик в Windows, возможно, вам придется использовать другой моноширинный шрифт, например Courier New.
Для этой игры необходим моноширинный шрифт, чтобы независимо от того, сколько букв угадано, слова имели одинаковую длину. Если бы у букв была разная ширина, то при добавлении новых символов, которые больше или меньше знака подчеркивания, программе Flash пришлось бы заново перерисовывать текст.
Игре также необходим клип "actions", который реагирует на нажатие клавиш и передает информацию о нажатой клавише сценарию основной временной шкалы.
На экране только два активных элемента, и то это два почти идентичных динамических текстовых поля. Первое, называющееся decryptedText, связано с переменной decrypted, оно чуть повыше чем второе, названное encryptedText и связанное с переменной encrypted. Шрифт второго поля также чуть светлее.
Оба текстовых поля используют шрифт Courier New, поэтому все буквы занимают одинаковое место, как в игре "Виселица".
Подход
Как и в предыдущем ролике, вопросы и ответы будут загружены из внешнего текстового файла. Однако текстовый файл будет немного отличаться. В предыдущей игре ответы были представлены в определенном порядке, и дополнительный элемент указывал, какой ответ верный. Сейчас же правильный ответ всегда будет располагаться первым, а далее будут следовать три неправильных ответа. Такое допустимо, так как ответы все равно будут перемешаны. Вот несколько строк из текстового файла flashtrivia.txt:
questions=The world's first computer bug was actually a real bug
stuck in an early computer. What type of bug was it?:
Moth;Beetle,-Fly;Worm:
Which is the world's largest Island?:
Greenland;Iceland;Australia;New Zealand:
Besides humans, what other animal also has individual
fingerprints?:Koala Bears;Apes;Snakes;Frogs:
Вопросы=Какого типа был первый компьютерный вирус?
:Моль;Жук;Муха;Червь:
Как назывется самый большой остров в мире?
:Гренландия;Исландия;Австралия;Новая Зеландия:
Кроме людей, какие еще животные имеют уникальные отпечатки
пальцев?:Коалы;Обезьяны;Змеи;Лягушки.
Так же, как и при работе над предыдущим проектом, будьте внимательны: не вставьте нечаянно пустую строчку в конце текстового файла. Она появится, если вы нажмете клавишу Return или Enter после ввода последнего вопроса. Если в конце текстового файла будет вставлена пустая строка, она будет рассматриваться как одиннадцатый вопрос.
Перед тем как задается вопрос, ответы в новом массиве перемешиваются случайным образом. Правильный ответ может оказаться по счету любым из четырех вариантов. Его положение присвоено некоторой переменной.
Здесь будет использоваться такая же анимация, как и в предыдущей игре, но немного ускоренная. Вопрос будет появляться сразу же, без анимации, но ответы будут быстро "въезжать" справа. Количество возможных очков будет уменьшаться только после того, как все четыре ответа окажутся на месте.
Когда пользователь выбирает неправильный ответ, количество возможных очков уменьшается на определенную величину, но и выбранный ответ исчезает.
В игре производится множество действий с символами. Фраза, которую нужно угадать, представляет собой строку символов. Из нее вы создаете строку, в которой вместо букв находятся знаки подчеркивания. Это как раз то, что увидит пользователь.
Когда игрок угадывает букву, она сравнивается с каждой буквой исходной фразы. Если буква совпадает с какой-либо буквой фразы, она отображается на экране на своем месте (или местах).
Если игрок не угадывает, клип с лисой переходит к следующему кадру, в котором добавляется новый фрагмент изображения лисы. Если это последний кадр клипа с лисой, игра заканчивается.
В игре используются две карты букв. Первая карта букв ставит в соответствие каждую букву алфавита ее зашифрованному двойнику. Вот, например, такая карта
ОПФКТИЭШСЕЙГРМЛАБНЗДЯВЩЧЦЖХЪЮЬЁЫУ.
В этой карте первая буква алфавита, А, закодирована как О. Вторая буква, Б, закодирована как П и так далее. С помощью этой карты "Как дела" закодировано как "Гог тиро". Вторая карта букв - та, с помощью которой игрок расшифровывает головоломку. Она начинается так:
АБВГЛЕЁЖЗИЙКЛМНОПРСТУФХЦЧШШЪЫЬЭЮЯ.
Когда игрок расшифровывает одну из букв, его карта букв изменяется. Например, он решает, что Г соответствует К, тогда карта играющего примет такой вид:
АБВКДЕЙЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ.
Взяв фразу и пользуясь первой картой букв, вы получаете закодированную фразу, которая может быть использована в криптограмме. Потом, когда зашифрованная фраза пропущена через созданную игроком карту букв, она расшифровывается обратно к своему первоначальному состоянию в том случае, если игрок создал правильную карту букв.
В этой игре пользователь может двигаться вперед и назад по буквам головоломки, используя клавиши со стрелками. Когда он нажимает клавишу с буквой, в карте букв выбранная буква заменяется на ту, клавиша которой нажата.
На рисунке 12.6 показана игра в процессе. Верхние буквы - это те, которые пользователь уже расшифровал. Нерасшифрованные буквы показаны звездочками. Нижние буквы - это зашифрованная фраза. Только верхние буквы меняются по мере разгадывания игроком головоломки.

Рисунок 12.6 В криптограмме нижние буквы - это зашифрованное послание, а верхние буквы меняются в зависимости от выбора игрока. Последняя буква в первой строке выделена полужирным шрифтом, поскольку это буква, которая только что выбрана
Создание кода
Код этой игры невелик по объему, но, тем не менее, разделен на несколько фрагментов. В первом кадре находится код, загружающий вопросы из внешнего файла.
Сценарий начинается с создания нового объекта LoadVars. Этот объект с помощью своих свойств позволяет решать набор специфических задач,связанных с загрузкой переменных. Вы можете получать информацию о том, что данные были отправлены на сервер или загружены с сервера.
Поскольку вам нужен ответ от сервера, то изначально необязательно устанавливать какие-либо свойства объекта LoadVars. Подробнее мы рассмотрим эти приемы в главе 17 "Сложные приемы". Метод load объекта LoadVars обращается к серверу и загружает данные.
Метод load объекта LoadVars осуществляет загрузку, обращаясь к указанному URL. Файл данных должен иметь вид "имя переменной = данные". Например, в результате обращения к текстовому файлу myVariable=Hello переменной myvariable будет присвоено значение Hello. Поскольку обращение происходит к удаленному серверу, может пройти некоторое время между вызовом команды load и загрузкой данных.
Итак, в начале сценария создается новый объект loadQuestions. С помощью метода load он обращается к файлу Flashquiz.txt.
Свойство onLoad объекта LoadVars определяет функцию, которая вызывается, когда загрузка завершена. В этом случае будет вызвана функция initQuestions.
После выполнения команды LoadVars. load данные из текстового файла будут доступны к использованию ActionScript. Например, если переменной myProperty присвоено значение myValue, то обращение loadQuestionsmyProperty. вернет значение myValue.
stop();
// Загружаем вопросы.
loadQuestions = new LoadVars();
loadQuestions.load("flashquiz.txt");
// Вызываем initQuestions, когда загрузка окончена.
loadQuestions.onLoad = initQuestions;
Функция initQuestions преобразовывает текстовую строку в массив, состоящий из вопросов, ответов и номера правильного ответа для каждого вопроса.
Вот как выглядит первая часть файла Flashquiz.txt. Первая строчка присваивает свойству topic текст "The Planets". С помощью обращения loadQuestions.topic сценарий получит доступ к этому значению и присвоит его переменной topic. Результат отобразится в динамическом текстовом поле.
Первый фрагмент кода находится в первом кадре главной временной шкалы. По существу это тот же самый код, который применялся в предыдущей игре для загрузки вопросов из текстового файла. Когда вопросы загружены, вызывается функция initQuestions, расположенная в основной временной шкале:
stop () ;
// Загружаем список вопросов.
loadQuestions = new LoadVars();
loadQuestions.load("flashtrivia.txt") ;
loadQuestions.onLoad = initQuestions;
Функция initQuestions разбивает строчку на две части, первая часть- вопрос, вторая - ответы. Затем она отделяет ответы друг от друга.Вся информация хранится в массиве qArray.
function initQuestions(quesions) {
// Выделяем вопросы,
qarray = questions.split(String.fromCharCode(13));
// Отделяем вопрос от ответов,
for (i=0;i
qArray[i] = qArray[i].split(":");
// Отделяем ответы друг от друга.
qArray[i][1] = qArray[i][1].split(";");
}}
Наибольшая часть кода находится в кадре "play", то есть в том кадре, где задаются вопросы, и пользователь должен на них ответить. Сначала функция initGame обнуляет счет и выводит первый вопрос.
function initGame() {
// Определяем переменные.
questionNum = 0;
score = 0;
// Выводим первый вопрос.
displayQuestion();
}
Функция displayQuestion берет следующий вопрос и помещает вопрос и ответы в соответствующие текстовые поля. Она также устанавливает количество возможных очков за правильный ответ на данный вопрос равным 1000.
function displayQuestion() {
// Проверяем, все ли вопросы заданы,
if (questionNum >= qArray.length) {
// Отображаем окончательный счет, завершаем игру.
gotoAndPlay("game over");
} else {
// Перемешиваем ответы.
answers = shuffleArray(qArray[questionNum][1].slice(O) ) ;
// Выводим вопрос и ответы на экран,
question.text = qArray[questionNum][0];
answerO.text = answers[0];
answerl.text = answers[1];
answer2.text = answers[2];
answer3.text = answers[3];
// Отображаем номер вопроса.
questionNumDisplay = questionNum+1;
Основные фрагменты кода находятся в главной временной шкале, там всего три функции.
Первая определяет фразу в начале игры. Она проверяет все символы фразы и создает отображаемую строчку, состоящую из знаков подчеркивания. Именно такую строчку игрок видит в начале игры.
function initGame() { //
Задаем фразу,
phrase = "Imagination is more important than knowledge";
// Создаем отображаемую строку.
display = "" ;
for (i = 0; i
// Рассавляем пробелы там, где нужно.
if (phrase.charAt(i) == " ") {
display = idsplay + " ";
} else {
// Заменяем буквы знаками подчеркивания,
display = display + "_";}
}}
Функция charAt возвращает символ, расположенный на определенном месте в строке. Как во многих функциях языка ActionScript, первый символ располагается в позиции 0.
Каждый раз, когда пользователь нажимает клавишу, клип "actions" передает код символа в функцию makeGuess. Первое, что делает эта функция, - преобразовывает код в букву.
Переменная letter проверяется функцией isAlpha на соответствие какой-либо букве, то есть такие клавиши, как пробел иди клавиша с цифрой или другие, просто игнорируются. Более подробно мы рассмотрим функцию isAlpha позднее.
Затем функция makeGuess просматривает каждую букву, чтобы выяснить, совпадает ли она с выбранным символом, во время этого процесса заново формируется переменная display. Каждое найденное совпадение помешается в данную переменную, в которой уже содержатся те буквы, которые совпали ранее.
Функция fromCharCode получает число, например 65, и преобразует его в символ, такой как "А". У всех символов есть соответствующий код. Числа от 65 до 90 относятся к заглавным буквам. Числа от 97 до 122 - к прописным (имеется в виду английский алфавит); 32 обозначает пробел. Полный список символов и их кодов можно найти в документации по Flash.
Изначально переменной gotOne присваивается значение false. Если найдено хотя бы одно совпадение, оно изменяется на true. Если в конце цикла значение переменной все еще равно false, значит, игрок не угадал букву, и клип с изображением лисы переходит к следующему кадру.
Необычность этого ролика в том, что весь код помешается в сценарии одного кадра. Весь целиком. Нет ни единой кнопки или клипа. Библиотека этого ролика совершенно пуста.
Сценарий кадра начинается с вызова функции initGame. Она задает фразу и создает карту букв. Карта букв игрока вся состоит из звездочек, обозначающих каждую букву. Результатом должны стать звездочки вместо каждой буквы в расшифрованном текстовом поле. Карта расшифровки, названная letterMap, задается вызовом функции createLetterMap. Вы также можете видеть еще не написанные функции showPhase и showCursor. Первая обновляет текстовое поле на экране, используя последнюю версию карт букв. Вторая выделяет только что выбранную букву полужирным шрифтом. Переменная charpos представляет, какая буква выбрана.
Листенеры - это новое добавление версии Flash MX. Листенер сообщает Flash, что событие произошло, и пора включать набор команд или функцию. Код может создать листенер, определив сначала стандартный объект. Событие, за которым должен следить листенер, в данном случае onKeyUp, задано так, что связано с функцией. Потом команда addListener присоединяет этот объект к объекту Flash, в данном случае объекту Key. Только определенные Flash объекты могут иметь листенеры, и эти листенеры могут быть использованы только для определенных событий, связанных с этими объектами. Например, листенер Key может следить только за событиями onKeyUp и onKeyDown.
В конце функции initGame создается листенер (прослушиватель) клавиатуры, который удостоверяется, что функция getLetter вызывается всякий раз, как игрок нажал клавишу.
initGame() ;
stop() ;
function initGame () {
// Используемая фраза.
phrase = "Imagination is more important than knowledge.Albert Einstein";
// Определяем переменные. createLetterMap();
userMap = "***************";
charpos = 0;
// Показываем курсор и фразу.
showPhrase();
showCursor(};
// Отслеживаем нажатие клавиши.
keyListener = new Object ();
keyListener.onKeyUp = getLetter;
Викторина во Flash
Исходный файл: Flashquiz.fla
Первые две игры, которые вы создадите в этой главе, построены по принципу вопросов и ответов. Первая игра - викторина с десятью вопросами, для каждого из которых дано четыре варианта ответа. Выбрав ответ, игрок видит, правильный он или нет.
На рис. 12.1 представлен основной кадр игры. Вопрос расположен вверху, а четыре варианта ответа - под ним. Пользователь должен щелкнуть по кнопке слева от ответа.

Рисунок 12.1 В основном кадре игры показан вопрос и четыре варианта ответа
в создании развернутого варианта викторины
Цель проекта состоит в создании развернутого варианта викторины основанного на предыдущем ролике. Ответы будут представлены не в одной и той же последовательности, а каждый раз будут отображаться в произвольном порядке.
Потенциально каждый вопрос стоит 1000 очков. Но чем дольше пользователь думает над ответом, тем меньше очков получает. Если пользователь дает неправильный ответ, он теряет определенное число возможных очков. Когда же, наконец, пользователь даст правильный ответ, количество оставшихся возможных очков будет прибавлено к его счету.
Цель проекта - воссоздать классическую игру "Виселица" в среде Flash. Игрок может с помощью клавиатуры угадывать буквы. Программа показывает буквы и рисует повешенного человека или, как в рассматриваемом примере, лису.

Рисунок 12.5 Игра "Виселица" проиграна
На рис. 12.5 изображен основной кадр игры, где рисунок с повешенной лисой закончен и открыты некоторые буквы. В данном случае игра только что была проиграна.
Криптограмму обычно решают с помощью карандаша и бумаги. Компьютер сильно облегчает разгадку такой головоломки. В бумажной версии игры, если игрок отгадал, что 3 означает Е, он должен найти все 3 и заменить их на Е. Если же он или она свое мнение поменяет, все Е придется стереть.
Игра делает это автоматически. Когда игрок задает, что 3 соответствует Е, все 3 в головоломке немедленно заменяются на Е. Если же игрок потом изменяет свое решение, все 3 легко могут быть заменены на А.
На экране отображается кадр
Рисунок 12. 2 На экране отображается кадр "loading" до тех пор, пока не будут загружены все вопросы
Каждое из пяти основных текстовых полей помечено в клипе словом "text". Один клип называется "question", остальным присвоены имена от "answer0" до "answer3". Так сделано для того, чтобы не создавать простые текстовые поля и иметь возможность перемешать клипы на рабочем поле (об этом эффекте будет рассказано далее).

Рисунок 12.3 Кадр "start game" виден, пока пользователь не щелкнет по кнопке начала игры
Другие возможности
Эта игра - самая простая из программ составных картинок-загадок, Вы без труда можете ее усовершенствовать. Например, можно зaпoминать исходное положение элемента при перетаскивании, а затем возвращать его на место, если игрок неправильно поместил его.
Еще один способ сделать игру интереснее - написать функцию, которая будет проверять, все ли элементы уже находятся на своем месте и если да, будет осуществлять переход к кадру с поздравлением с победой. Можно усложнить игру, создав более 24 кусочков, тем самым получив больше мелких элементов.
Если хотите, позвольте игроку поворачивать каждый элемент на 90°, 180° или 270°. Для этого пользователь мог бы нажимать клавишу Пробел. Элемент будет фиксироваться в своем положении только в том случае, если он правильно повернут.
Конечно, есть более сложные варианты, например, картинки-загадки, у которых нет очерченного контура. Игрок может соединить два или более элементов в любом месте экрана, а затем прикрепить их к целой картине. Однако для такой игры потребуется написать большой сценарий. Вместо этого давайте перейдем к другому виду составления картинок.
Игра будет интереснее, если программа будет определять, когда картинка полностью собрана, и на экране будет появляться кадр с поздравлением. Это можно сделать, сохранив исходное положение элементов в массиве и выясняя после каждого шага, в нужном ли месте оказался элемент. Когда все позиции совпадут, картинка собрана.
Самый простой способ изменить эту игру - добавить фоновый рисунок, который будет отображаться за картами. Картинки на картах могут соответствовать теме фоновой картинки. Вы можете выбрать практически любую тему. Также в первый кадр клипа "Cards" нетрудно добавить картинку для рубашки карты.
Хотя в примере 36 карт, ничто не мешает вам уменьшить или увеличить это число. Просто не забудьте откорректировать размер сетки, а также длину массива в начале игры. Если число карт не будет вписываться в квадратную сетку, вам понадобится изменить код или написать новый, чтобы определить расположение карт.
Еще одна возможность - использовать четыре однотипные карты, а не две. Так будет гораздо проще найти совпадения.
Если вы хотите, чтобы игра определяла, когда найдены все совпадения, добавьте счетчик, который будет увеличиваться при каждом совпадении. Когда счетчик станет равен 18, игра закончится. Затем можно перейти к кадру "you win".
Вам должно быть легко добавлять картинки в эту игру. Вы можете иметь их столько, сколько хотите. Только помните, что надо установить код, узнающий последнюю картинку в обработчике onMouseDown.
Вы также можете сделать клип "button" больше, чем 36x36. Помните только, что тогда вам придется переделать функцию setUpRound так, чтобы она помещала кнопку дальше, чем на 18 пикселов от каждого края.
Вместо растрового изображения вы можете использовать векторный рисунок. Это сделает игру более простой и доступной для маленьких детей. Сделав соответствующее оформление и добавив анимационное вступление, можно создать хорошую игру даже для самых маленьких детей, которые еще не умеют читать.
Игра совпадений
Исходный файл: Matching.fla
Следующая программа, наверное, является самой популярной Web-игрой. Существуют ее варианты, созданные с помощью Shockwave, Flash, Java, JavaScript и даже простого HTML с применением CGI. Такую игру просто создать, в нее быстро привыкаешь играть и ее легко можно приспособить для любого сайта или ситуации.
Игра совпадений (или игра памяти, как ее иногда называют) использует сетку с картами, расположенными рубашками вверх. Существует две карты каждого типа. Игрок может одновременно открыть две карты. Если они совпадают, карты удаляются. В противном случае обе карты снова переворачиваются рубашками вверх. Игрок пытается запомнить, где какая карта расположена, чтобы было проще отыскать совпадения.
На рис. 13.4 показан фрагмент этой игры (файл Matching.fla): в ней 36 карт, из которых четыре уже удалены и две только что открыты. Эти две карты не совпадают, следовательно, они снова будут перевернуты, как только игрок выберет следующую карту.

Рисунок 13.4 Цель игры совпадений - удалить все карты, чтобы стала видна фоновая картинка
К сведению
В рассмотренном варианте игры элементы мозаики расположены друг от друга на расстоянии 54 пиксела, а игровое пространство представлено сеткой 4x4. Если вы хотите изменить один из этих параметров, необходимо тщательно проверить код и внести необходимые изменения.
Не забудьте вставить команду stop () в первый кадр клипа "Cards". В противном случае во всех картах будут отображаться все картинки.
Клип "maskedPicture", кроме маски и картинки, содержит еще границы слоя, соответствующие маске. Это помогает ему выделяться на экране. Также в каждом кадре ролика содержатся статичные участки текста, объясняющие играющему, что происходит.
Вы можете задать свойства каждого растрового изображения, чтобы определить уровень сжатия и сглаживание. Вам придется потрудиться, пока вы не добьетесь удовлетворительных результатов.
Найди картинку
Исходный файл: Findthepicture.fla
Эта игра необычная, ее можно найти скорее в книге пазлов, чем на компьютере. Создание Flash-версии этой игры помогает показать несколько полезных приемов.
В игре "Найди картинку" игрок ищет не целую картинку, а ее сегмент. Целиком картинка показана; справа, а слева показана ее увеличенная часть. Задача состоит в том, чтобы быстро найти место увеличенного сегмента на целой картинке.
Игра показана на рис. 13.6. Сегмент слева выбран случайно и увеличен в три раза. Игрок должен щелкнуть по соответствующему месту большой картинки. В зависимости от того, насколько быстро он нашел правильное место, начисляются дополнительные очки.

Рис. 13.6 В этой игре ваша задача найти место маленького изображения слева на большом изображении справа
Пазл
Исходный файл: Jigsawpuzzle.fla
Игра "Пазл" состоит из элементов одного размера, которые, соединяясь, образуют целостное изображение. Обычно они сделаны из картона и для составления картинки требуется большая площадь, например, обеденный стол. Так как экран монитора слишком мал по сравнению со столом, создать компьютерный аналог такой игры очень сложно.
Однако в упрошенном варианте подобная игра вполне применима для Web-сайта в качестве развлекательного материала. На рис. 13.1 показан кадр ролика Jigsawpuzzle.fla. На игровом поле имеются 24 элемента картинки и пустая сетка, куда эти элементы должны быть помещены.

Рисунок 13.1 Пазл почти собран
Подготовка ролика
Так как же я создал 24 элемента в игре? На самом деле, это была самая сложная часть работы. Однако здесь нет ничего сверхъестественного. просто данный процесс отнимает много сил. /Зля тех, кто хочет знать, я постараюсь объяснить. Нет одного универсального способа создания элементов с помощью Flash-графики, каждый выбирает то, что ему больше нравится.
Я начал с изображения, которое представляло собой набор линий и областей на одном слое, после чего преобразовал все линии в области, так чтобы в изображении остались только сплошные области.
Затем я создал кадр для мозаики (см. рис. 13.1). Я нарисовал только небольшую часть сетки вдоль направляющих Flash, затем скопировал и вставил этот кусочек несколько раз, так что получилось очертание картинки (как в пазле).
Затем каждую область сетки залил красным цветом и выделил все залитые области, кроме той, которая предназначена для элемента мозаики в верхнем правом углу. Скопировал выделение и вставил его в верхнюю часть моей картинки. Потом выделил и удалил всю красную область, таким образом, на рабочем поле остался только один элемент.
Так как мои действия уничтожили созданное ранее, я сохранил копии очертания и картинки в других слоях. Теперь я могу повторить эти действия для создания следующей картинки. Для 24 элементов пришлось проделать это 24 раза.
Когда все было сделано и получилось 24 клипа, понадобилась сетка для повторного выравнивания элементов, так чтобы их центр располагался в нужном месте. Для завершения мне понадобилось 20 минут. Однако, возможно, вы сделаете то же самое гораздо быстрее. ,
После того как у меня получились все элементы, я поместил экземпляр каждого клипа на рабочее поле и присвоил экземпляру клипа имя, соответствующее имени самого клипа. 24 элемента называются от "0-0" до "5-3" в зависимости от вертикального и горизонтального положения элемента. Однако я разместил элементы вокруг границы рабочего поля в произвольном порядке. Также каждому клипу присвоил значение _apha=75. Затем я поместил клип контура картинки в центр и назвал его "outline".
Можно воспользоваться любым понравившимся вам методом создания элементов. Чтобы получить 15 элементов, я выделял квадраты на графическом изображении. В отличие от элементов составной картинки-загадки здесь не нужно размешать их определенным образом. Центром каждого элемента мозаики может бьпъ его собственный геометрический центр. То есть для этой игры создать элементы гораздо проще.
После того как вы создали все элементы, поместите их на рабочее поле так, как они должны располагаться в собранной мозаике. Я сделал кусочки размером 54x54 пиксела, то есть они должны бьпъ расположены друг от друга на расстоянии 54 пиксела как по вертикали, так и по горизонтали. Поскольку Flash не гарантирует точность при размещении клипов вручную, даже если показана сетка, выравнивать элементы перед началом игры лучше с помощью ActionScript.
Очень важно поместить элементы близко к их исходному положению и присвоить им имена. Я дал им имена от tilel до tileis, чтобы к ним можно было обращаться в коде программы.
В ролике Matching.fla есть клип "Cards", временная шкала которого содержит 19 кадров (рис. 13.5).

Рисунок 13.5 Во временной шкале клипа "Cards" имеется 19 кадров, первый без картинки и остальные 18 с различными картинками
В первом кадре расположена рубашка карты, то есть никакой картинки нет. В остальных 18 кадрах содержатся изображения, соответствующие разным картам.
Кнопка - просто прямоугольник такого же размера, что и карта. Она расположена в третьем слое клипа "Cards" (см. рис. 13.5), то есть за фоном.
Хотя кнопку не будет видно, она будет реагировать на действия пользователя.
Также в клипе "Cards" присутствует фон. У первого кадра, содержащего рубашку карты, фон серый. У остальных кадров, в которых находится какая-либо картинка, белый фон.
Имя эталона основного клипа в библиотеке — "picture". Он содержит три растровых изображения, по одному в каждом кадре. В первом кадре находится команда stop (). Картинки выстроены так, что верхний левый угол каждой располагается в центральной точке клипа.
Клип "picture" никогда не находится в рабочем поле сам по себе, а внутри двух других клипов: "fullPicture" и "maskedPicture".
В клипе "fullPicture", клип "picture" находится на одном слое, а маленький квадратный клип "button" - поверх него в другом слое.
В клипе "maskedPicture" клип "picture" также находится на одном слое, а клип "button" - на другом. Однако слой кнопки - это слой-маска, маскирующий слой картинки. Это значит, что только сегмент картинки под квадратом остается видимым, когда клип "maskedPicture" расположен в рабочем поле.
В рабочем поле клипы "fullPicture" и "maskedPicture" расположены бок о бок. Размешать клип "maskedPicture" достаточно сложно, поскольку, когда вы его двигаете, он показывает свои границы, которые довольно велики и покрывают все рабочее поле. Як тому же увеличил этот клип до 300%, что сделало его еще больше.
Главная временная шкала содержит четыре кадра. Первый - это страница с правилами. Потом идет кадр "play". Когда игрок заканчивает одну картинку, ролик переходит к кадру "next", чтобы дать игроку передохнуть перед следующей картинкой. Последний кадр - это кадр "game over".
В ролике используются два динамических текстовых поля. Первое, displayBonus, используется в кадре "play". Поле displayScore используется в кадрах "next" и "game over".
Подход
Для создания этой игры можно просто прикрепить небольшой сценарий к клипу "actions", расположенному вне рабочего поля. Когда пользователь щелкнет по рабочему полю, сценарий определит, какой элемент находится под курсором, затем этот элемент будет перетаскиваться с использованием стандартных возможностей Flash.
Когда кнопка мыши отпускается, код определяет, находится ли элемент мозаики рядом со определенным для него местом, и, если да, элемент фиксируется.
Сначала устанавливаем для всех клипов, содержащих элементы мозаики, свойство _alpha=75, чтобы они стали немного светлее. Затем, когда игрок поместит элемент на свое место, соответствующий клип станет полностью непрозрачным. Таким образом, будет обеспечена некая обратная связь с игроком, ему будет сообщаться, что элемент находится на своем месте. Также будет проверяться, является ли элемент мозаики полностью непрозрачным в тот момент, когда пользователь щелкает по нему мышкой и начинает перетаскивать. Это необходимо, чтобы те элементы, которые уже находятся на своем месте, больше не перемешались.
Узнать, находится элемент на своем месте или нет, несложно, потому что они сделаны таким образом, чтобы их центр находился в центре основной картинки. Например, у элемента из верхнего левого угла центр будет правее и ниже (рис. 13.2).
Теперь представьте, что каждый элемент создан именно так. Центр элемента останется в центре картины не зависимо от того, где он будет располагаться. Если вы не совсем поняли, что я имею в виду, просмотрите исходный ролик Jigsawpuzzle.fla. Изучите несколько клипов, содержащих элементы мозаики, и увидите, что центр остается постоянным.
Это намного упрощает код. Каждый элемент должен быть помещен точно на свое место, чтобы вписаться в контур картинки. Так что способ определения надлежащего положения элемента будет одинаковым для всех клипов.

Рисунок 13.2 Центр этого элемента определяется по отношению к центру всей картинки
Большая часть рассматриваемой программы представляет собой по сути подготовку к собственно игре, обеспечивая перемешивание элементов мозаики. Сначала случайным образом выбирается элемент. Потом выполняется проверка, является ли один из четырех смежных элементов пустым. Если да, то выбранный элемент перемещается туда. В противном случае выбирается другой элемент до тех пор, пока не будет найден элемент, смежный с пустым квадратом. Этот процесс повторяется 100 раз.
Когда перемешивание закончено, пользователь может передвигать элементы сам. Когда он щелкает по элементу, код проверяет, есть ли рядом с этим элементом пустой квадрат, если да, выбранный элемент перемещается туда.
В игре используется только два библиотечных элемента. Первый – клип, в первом кадре которого представлена рубашка карты. В остальных кадрах содержатся картинки. Так как будет 18 различных картинок, в клипе окажется 19 кадров. Если вы хотите, чтобы клип отобразил рубашку, карты, перейдите к первому кадру; если хотите увидеть картинку, перейдите к одному из кадров 2-19.
Второй элемент библиотеки - кнопка, расположенная внутри карт клипа Она будет использоваться для реагирования на действия пользователя.
Игра начинается с создания 36 клипов, помещенных в сетку на рабочем поле. Каждый клип отображает рубашку карты, но если карта перевернута, показывается другая картинка. Каждая картинка будет содержаться в двух клипах, таким образом, получится 18 пар карт.
Когда игрок выбирает первую карту, отображается соответствующая ей картинка. Когда игрок выбирает вторую карту, она тоже переворачивается и появившаяся картинка сравнивается с первой открытой картой. Если они совпадают, карты удаляются, в противном случае ничего не произойдет до тех пор, пока игрок не щелкнет еще раз. Тогда первые две карты переворачиваются обратно, и отображается картинка новой выбранной карты.
Способ, каким сегмент картинки отображается на экране, основан на использовании слоев. В клипе картинка находится на одном слое, а маленький квадрат используется как маска для этого слоя. Только та часть картинки, которая находится под квадратом, оказывается видимой, когда клип отображается на экране.
Картинка имеет размер 400x300. Квадрат - размер 36x36. Когда картинка передвигается под квадратиком маски, видна только та часть картинки размером 36x36, которая находится под квадратом. Хотя перемещение
картинки сделано в ActionScript, маска создана во временной шкале клипа во время подготовки ролика.
Когда пользователь отмечает положение сегмента на целой картинке, ему нужно щелкнуть по этому месту. Было бы естественно расположить на этом месте невидимую кнопку, дело только в том, что кнопка должна сама себя уничтожить, поскольку курсор пользователя заменяется на руку. Вместо этого поместите обычный клип на это место и используйте hitTest, чтобы определить, когда по нему щелкнут.
В ролике используются Flash МХ-листенеры, чтобы поместить весь код в главную временную шкалу. Это значит, что реакция на щелчок мыши и обслуживание изменяющегося таймера должны быть частью сценария главной временной шкалы, а не одного из "actions''-клипов.
С помощью Flash MX и Flash 6 плеера стало возможным делать почти что угодно с помощью всего лишь одного сценария в главной временной шкале. Для этого необходимо регистрировать события, такие как onMouseUp и onEnterFrame, в функциях. Это может заменить обработчик onclipEvent в "actions''-клипах. Но поскольку эта технология не совместима сверху вниз с Flash 5, может пройти некоторое время, прежде чем она начнет широко применяться.
Эта игра показывает не одну картинку, а три. Общее число набранных игроком очков складывается из бонусных очков, полученных за все три картинки. Сыграйте прямо сейчас, чтобы познакомиться с игрой.
Создание кода
Весь сценарий прикреплен к клипу "actions", расположенному за пределами рабочего поля. Он начинается с обработчика событий onClipEvent (mouseDown), который реагирует на щелчок мыши по рабочему полю.
Этот код просто просматривает элементы картинки и определяет, находится ли один из них под курсором, а также является ли элемент полностью непрозрачным, то есть размещен ли на своем месте.
Если элемент найден, программе Flash сообщается, что теперь он подвижный и может перемещаться с помощью команды startDrag. Затем программа завершается.
Команда startDrag - основное действие, позволяющее пользователю перетаскивать клип. Оно не такое универсальное, как методы перетаскивания, рассмотренные ранее, но в простых случаях работает хорошо. Команда stopDrag останавливает перетаскивание.
onClipEvent(mouseDown) {
// Определяем положение курсора.
mx = _root._xmouse;
my = _root._ymouse;
// Просматриваем все элементы картинки,
for (x=0;x
for(y=0;y
piece = _root[x+"-"+y];
// Выясняем, находится ли элемент под курсором
// и не находится ли он уже на своем месте?
if (piece.hitTest(mx,my) and (piece._alpha < 100)){
// Пользователь щелкнул по элементу.
piece.startDrag();
// Выходим из циклов.
х = 6 ;
У = 4;
break;
}}
}}
Когда пользователь отпускает кнопку мыши, элемент фиксируется, Код проверяет расстояние от центра элемента до центра контура: если оно не превышает 10. пикселов, элемент перемешается точно в свое положение и становится полностью непрозрачным, так что пользователь видит: элемент находится на своем месте.
onClipEvent(mouseUp) {
// Прекращаем перемещение элемента.
stopDrag();
// Измеряем расстояние от центра элемента до центра контура.
dx = _root.outline._x - piece._x;
dy = _root.outline._x - piece._y;
dist = Math.sqrt(dx*dy+dy*dy);
// Если расстояние меньше 10 пикселов,
// элемент помещается на свое место,
if (dist < 10) {
piece._x = _root.outline._x;
piece. _y = _root.outline._y;
// Делаем элемент полностью непрозрачным,
piece._alpha = 100;
}
}
Большая часть кода находится в основной временной шкале. Он начинается с выравнивания элементов на расстоянии точно в 54 пиксела, затем 100 раз выполняется цикл, перемещающий случайно выбранный элемент на пустую позицию.
function initGame() {
// Устанавливаем горизонтальное и вертикальное расстояние
// между элементами.
tileDist = 54;
// Помещаем все элементы на свои места,
for (x=l;x
for (y=0;y
tile = х+у*4;
_root["tile"+tile];
_x = x*tileDist;
_root["tile"+tile];
_y = y*tileDist+tileDist;
}}
// Совершаем 100 произвольных перемещений,
for(tilenum=0;tilenum
do {
// Выбираем элемент случайным образом.
tile = "tile"+(random(15)+1);
//- Проверяем, есть ли рядом свободный квадрат.
emptySpace = findEmpty(tile);
// Цикл продолжается до тех пор, пока не будет найден
// элемент, рядом с которым расположен свободный квадрат.
} while (emptySpace == "none");
// Перемещаем элемент на свободное место.
moveTile(tile,findEmpty(tile));
}}
Когда случайным образом выбирается элемент, с помощью функции findEmpty определяется, есть ли среди смежных элементов свободный квадрат. Прежде чем проверять элемент мозаики, обязательно убедитесь в том, что свободное место не находится за границей игрового поля.
// Проверяем, есть ли свободное место около данного элемента,
function findEmpty (tile) {
// Определяем положение элемента.
tilex = _root[tile]._x;
tiley = _root[tile]._y;
// Проверяем, есть ли элемент мозаики слева,
if (tilex > tileDist) {
if (!tileThere(tilex-tileDist, tiley)) {
return("left");
}}
// Проверяем, есть ли элемент мозаики справа,
if (tilex > tileDistM) {
if (!tileThere(tilex+tileDist, tiley)) {
return("right");
}} // Проверяем, есть ли элемент мозаики сверху. if (tiley > tileDist) { if (!tileThere(tilex, tiley-tileDist)) { return)"above");
}}
// Проверяем, есть ли элемент мозаики снизу,
if (tiley > tileDistM) {
if (!tileThere(tilex, tiley+tileDist)) {
Почти весь код этой игры находится в основной временной шкале. Ролик начинается с вызова функции initGame, которая создает список 18 пар карт, случайным образом выбирает карты из первого списка, а затем помешает их во второй список, чтобы перемешать колоду карт.
Потом функция создает 36 карт. Каждый клип автоматически начинается с того, что карта помещается рубашкой вверх, а свойству клипа ("picture") присваивается номер картинки, которую карта будет представлять.
initGame();
stop();
function initGame() {
// Создаем отсортированный список карт.
cardsListOrdered = [];
cardsListOrdered.push(i,i);
}
// Список перемешанных карт.
cardsListSorted = [];
while (cardsListOrdered.length > 0) {
r = int(Math.random()*cardsListOrdered.length);
cardsListSorted.push(cardsListOrdered[r]};
cardsListOrdered.splice(r,1);}
// Создаем клипы карт и определяем их положение и картинки,
х = 0; У = 'О; for(i=0;i
attachMovie("card", "card" + i, i) ;
_root["card"+i].picture = cardsListSorted[i];
_root["card"+i]._x = x*60+200;
_root["card"+i]._y = y*60+50;
// Переходим к следующей карт
х++;
if (х > 5) {
х = 0;
У++;
}}
// Располагаем эти две карты рубашками вверх,
firstclip.gotoAndStop(1);
secondclip.gotoAndStop(1);
firstclip = 0; secondclip = 0;
firstdip = 0;
}
Обратите внимание, что с помощью команды push в массив можно добавить сразу более одного элемента, Например, выражение myArray.push(7,12) добавит в массив myArray числа 7 и 12.
Функция initGame заканчивается тем, что обнуляется переменная firstclip. В этой переменной содержится ссылка на карту, по которой щелкнули первой. Когда щелкают по клипу, кнопка внутри этого клипа отреагирует и на основную временную шкалу с помощью функции clickCard будет добавлена ссылка к клипу.
Функция clickCard может выполнить одну из 3-х функций. Если значение переменной firstclip равно 0, ей присваивается клип, по которому щелкнули, карта переворачивается, то есть программа переходит к кадру, содержащему соответствующую картинку.
Если в переменной firstclip хранится ссылка на некий клип, значит, одна карта уже перевернута. В этом случае программа пepeвopaчивает и вторую карту, присваивает переменной secondclip значение клипа и сравнивает два клипа. Если они совпадают, оба клипа удаляются.
Третье условие, которое, на самом деле, проверяется до двух первых, возникает тогда, когда игрок щелкает по одной и той же карте дважды. В таком случае значение переменной clip будет равно firstclip. Карта просто снова переворачивается и значение firstclip обнуляется.
Прежде чем проверить эти три условия, функция clickCard определяет, перевернуты ли уже две карты. Если да, значит, игрок уже выбрал две карты, но они не совпали. Прежде чем перевернуть следующую карту, эти две карты поворачиваются рубашками вверх
В начале ролика задаются функции roundNum и score. Переменная roundNum содержит номер картинки, которая должна появиться.
// Начинаем с первой картинки.
roundNum = 1;
score = 0;
stop();
Игра начинается, когда пользователь нажимает кнопку в первом кадре. Все коды содержатся на главной временной шкале, в первом слое. Нажатие кнопки вызывает функцию setUpRound.
После того как функция отправляет ролик к кадру "Play", она определяет два клипа. Содержащийся в каждом из них клип "picture" устанавливается в кадр, определяемый переменной roundNum.
После этого выбирается случайное место на картинке. Это происходит с учетом того, что площадь сегмента 36x36, таким образом, это случайное место должно быть не ближе 18 пикселов от края изображения.
В клипе "maskedPicture" положение картинки изменяется таким образом, что случайное место располагается в позиции (0,0), на которой располагается квадрат-маска. Таким образом, если сегмент выбрана из позиции (100, 150), то увеличенная картинка должна быть сдвинута на -100 пикселов по горизонтали и на -150 - по вертикали.
В клипе "fullPicture" картинка остается неподвижной, а движется клип "button", пока не займет нужное положение. Свойство _alpha равно 0, чтобы кнопка была невидимой.
Вместо того, чтобы задавать свойство _alpha клипа равным 0, попробуйте задать его равным 25 во время отладки программы. Поскольку клип будет видимым, вам будет легче понять, что игра работает.
function setUpRound(pictureNum) {
// Переходим к кадру игры. gotoAndStop("Play");
// Выбираем картинку в обоих клипах.
fullPicture.picture.gotoAndStop(pictureNum);
maskedPicture.picture.gotoAndStop(pictureNum);
// Задаем случайное положение картинки.
w = fullPicture._width;
h = fullPicture._height;
x = Math.random()*(w-36)+18;
у = Math.random))*(h-36)+18;
// Передвигаем картинку под маской в это положение.
maskedPicture.picture._x = -х;
maskedPicture.picture. _y = -у;
// Задаем координаты кнопки.
fullPicture.button._x = х;
создать простую, но от этого
Цель проекта - создать простую, но от этого не менее интересную игру "Пазл". Игрок сможет перетаскивать элементы мозаики с границы рабочего поля на сетку. Когда элемент окажется около того места, где должен располагаться, он будет зафиксирован.
Цель проекта заключается в создании простой, но при этом каждый раз разной игры совпадений. Игрок сможет выбрать одну карту, затем другую. Каждая карта будет перевернута при щелчке мышью, так что будет видна ее картинка. Если карты совпадают, они обе удаляются, в противном случае снова переворачиваются, как только пользователь выберет следующую карту.
Чтобы создать эту игру, ваш сценарий должен уметь выбирать случайный сегмент из большой картинки и показывать его рядом с ней. Это требует использования масок. Также ActionScript должен уметь сопоставить сегмент с соответствующей областью на большой картинке.
Кроме манипуляций с изображениями, в игру должен быть включен таймер. Таймер начинает с некоего большего числа и производит обратный отсчет. Когда игрок верно угадывает место сегмента на картинке, он получает дополнительные очки в зависимости от показаний таймера.
Цель проекта - создать простую, легкую игру по принципу "Пятнашек". Игрок будет щелкать по элементу: если рядом есть пустой квадрат, элемент будет перемешен.
Очень важно в начале игры случайным образом расположить элементы. Для этого Flash-ролик сначала нарисует все элементы мозаики на своих местах, а затем будет выполнено 100 произвольных перемещений. Таким образом, элементы окажутся перемешаны, и собрать такую мозаику будет сложно, но возможно.
Другие возможности
Тема игры может быть любой. Достаточно изменить фон и вид элементов. Количество элементов зависит о того, насколько сложной вы хотите сделать игру.
Важно помнить о том, что если вы хотите изменить какие -либо элементы игры, надо соответственно подкорректировать константы, представленные в начале кода. Если вы не будете о этом забывать, с игрой можно делать практически что угодно.
Чтобы изменить уровень сложности игры попробуйте изменить количество попыток угадать решение. Также можно увеличить или уменьшить число цветов и мест для них.
Один момент в этой игре пропущен - способ узнавать, когда игра закончилась. Вы можете поместить кнопку "I'm Done!" в кадре и дать возможность игроку решать, когда игра закончена.
Однако можно использовать ActionScript, чтобы определить два возможных пути завершения игры. Первый, это когда все блоки удалены. Это редкость; большинство игр оставляют несколько неудаляемых блоков. Но, если это случится, вы можете определить это, выясняя, не пуст ли самый нижний левый блок после того, как функция collapseDown запушена.
if (_root["block 0 11"]._currentFrame == 5) {
gotoAndStop("gameOver");
}
Большинство игр оставляет несколько блоков, не соседствующих ни с одним блоком своего цвета. Определить такой случай будет более трудной задачей.
Проще всего это сделать с помощью цикла по всем блокам, пропуская пустые и проверяя непустые, не соседствует ли с ними блок такого же цвета. Если есть хоть один такой блок, игра не считается законченной.
Главный способ изменения игры - создание другой доски. Существует множество вариантов, например, колышек можно перемещать не только по вертикали и горизонтали, но и по диагонали. В данном случае нужно переписать код.
Еще одно изменение - создать колышек, который по цвету отличается от других. Таким образом можно усложнить игру: последним нужно оставить именно этот колышек.
Игра "Йога"
Исходный файл: Pegs.fla
Классическая игра "Йога" известна уже тысячи лет. Современные версии сделаны из дешевого пластика. С развитием Web-технологий появился и виртуальный вариант этой игры.
Для игры требуется решетка с отверстиями для колышков (рис. 14.7). Колышки расположены во всех отверстиях, кроме одного. Игрок должен взять один колышек и "перепрыгнуть" через другой, при этом попасть на пустое место. Колышек, через который "перепрыгнули", при этом удаляется. Игра продолжается до тех пор, пока нельзя будет сделать больше ни одного передвижения.

Рисунок 14.7 Наиболее распространенная конфигурация доски с колышками. Вы можете создать свой вариант
Хороший игрок может выиграть, если у него останется только один колышек. При быстрой игре, без раздумий, может остаться примерно от 8 до 12 колышков.
Игра на развитие памяти
Исходный файл: Memory.fla
Иногда эту игру называют "Simon", потому что именно так называлось популярное электронное устройство, которое позволяло в нее играть. В игре имеется четыре разных фрагмента, которые проигрываются в произвольном порядке. Вы можете это увидеть, запустив файл Memory.fla. При проигрывании фрагмента загорается световое табло и воспроизводится звуковой сигнал. Элементами этой игры являются четыре птицы, сидящие на ветке (рис. 14.1).

Рисунок 14.1 В игре на развитие памяти на экране показаны четыре птицы
В игре две основные фазы. Первая фаза - птицы чирикают в определенной последовательности. Во второй фазе пользователь пытается воссоздать эту последовательность/Затем фазы повторяются, при этом добавляется еще одна мелодия. Очень скоро последовательность становитсянастолько длинной, что пользователь не может ее воссоздать, и игра заканчивается.
К сведению
Во всех шести кадрах ролика должна быть команда stop (). В кадрах со второго по шестой это единственная команда.
В кадрах "wait", "correct" и "wrong" находятся кнопки. В кадре "wait" кнопка переводит игру к кадру "play", где проигрывается последовательность мелодий. Кнопка кадра "correct" снова переносит игрока к кадру "play". Однако также должна быть вызвана функция addNewNote, чтобы добавить сообщение в последовательность.
on (press) {
addNewNote();
gotoAndPlay("play");
}
Кнопка в кадре "wrong" переводит ролик к кадру "start", где можно заново начать игру.
Также не забудьте добавить текстовое поле, связанное с переменной scoreDisplay, чтобы игроки знали о результатах своей игры.
He забудьте присвоить последним двум кадрам клипа "rock" метки "white” и "black". Также обязательно поместите кнопку Done внутрь клипа "done», которому потом необходимо присвоить имя "done" в панели Linkage Properties. К сожалению, это необходимо, так как ActionScript не может динамически создавать кнопки сами по себе. Считайте, что клип "done" - это просто "обертка" для кнопки Done.
В игре имеется поле score, помешенное под игровой областью. Оно отслеживает переменную score, которая увеличивается в процессе исполнения функции clickBlock.
Подготовка ролика
В ролике шесть кадров ( рис. 14.2). Из них кадры под номерами 3 и 4 -ключевые, они называются "play" и "repeat" соответственно. В кадре "play" воспроизводится чириканье птиц, а в кадре "repeat" игрок может щелкать по птицам.

Рисунок 14.2 Шесть кадров игры на развитие памяти: "start", "wait", "play", "repeat", "correct" и "wrong"
Клип каждой птицы состоит из трех частей. Первая - непосредственно клип с самой птицей, первый кадр которого представляет собой изображение, второй и остальные кадры - анимация (птица чирикает, открывая и закрывая рот). Ролик начинается с того, что клип каждой птицы находится в первом кадре.
Вторая часть клипа - кнопка. Одна и та же кнопка используется для каждой птицы, но к ней прикреплен разный код. Кнопка расположена за изображением птицы, так что ее не видно.
Третья часть клипа каждой птицы - просто анимация, показывающая сообщение, которое «вылетает» из клюва птицы. Этот простой клип используется для каждой птицы один раз. Экземпляр анимации сообщения и птица соответственно. Например, первая птица называется «bird1», а сообщение – “note1”. В анимации сообщения первый кадр пустой, там анимация останавливается. Во втором кадре анимации происходит возврат к первому кадру. В соответствующее время мы инициализируем сообщение, которое «вылетает» из клюва птицы.
Если вы внимательно посмотрите на элемент "Bird Button" из исходного ролика, вы увидите, что кадры "Up", "Over" и "Down" пусты, а в кадре "Hit" содержится контур птицы. Это значит, что никакого изображения на рабочем поле для кнопки не будет, а область нажатия кнопки будет совпадать с формой кадра "Hit". Такой способ создания невидимой кнопки отличается от уже описанного, когда создается кнопка и ее значение _alpha обнуляется.
Если рассмотреть анимацию птиц, вы увидите, что звук прикреплен к каждой из них. Звук автоматически воспроизводится при проигрывании анимации с птицей. Каждый звук немного отличается от другого.
В различных кадрах появляются различные части клипов птиц. Клипы
с изображениями самих птиц представлены во всех шести кадрах. Однако кнопки появляются только в кадре "repeat", потому что только там
игрок может щелкать мышкой по птицам. Анимация сообщения появляется только в кадрах под номерами 3-6, в первом и втором кадрах она не нужна.
Также в каждом кадре ролика содержатся указания, что должен делать пользователь. В верхнем правом углу всех кадров, кроме первого, находится текстовое поле scoreDisplay.
В клипе "rock" содержится восемь кадров, первый из которых показывает пустое место. Кадры со второго по шестой отображают пять цветов, из которых должен выбрать пользователь. Седьмой и восьмой кадры отображают белые и черные камешки, имеющие метки "white" и "black" соответственно, чтобы код мог обращаться к ним.
Теперь осталось поместить на рабочее поле фон и указания. Камешки и кнопка Done создаются кодом. Для клипа "rock" установите имя ("rock") в панели Linkage Properties. Я также создал небольшую кнопку, чтобы можно было перейти внутрь клипа камешка. Кнопку "0опе"создать очень просто, но так как нам нужно управлять ее положением, мы должны поместить ее внутри клипа и указать для него свойство "linkage".
Для игры требуется всего два клипа: "peg" и "hole". В клипе "peg" должна быть расположена кнопка, которая сообщает основной временной шкале о щелчке мышью (пользователь нажимает и отпускает ее кнопку). Так как перед началом ролика на рабочем поле нет ни одного клипа, им необходимо назначить свойства связи. Код обращается к ним по именами "peg" и "hole".
Ролик содержит довольно мало элементов, за исключением клипа в библиотеке, представляющего блоки. Этот клип содержит 4 кадра, по кадру для каждого цвета. Также в каждом кадре есть маленькая картинка. Пятый кадр пустой и представляет пустое место в решетке. Первые четыре блока имеют кнопку, чтобы по ним можно было щелкнуть. Клипу необходимо присвоить имя в панели Linkage Properties, поскольку он не находится изначально на рабочем поле.
Главная временная шкала ролика включает в себя два кадра: первый, содержащий инструкции и кнопку Play, а второй - это кадр "Play".
Подход
Последовательность мелодий хранится в массиве. Каждый раз в массив добавляется новый, случайный номер от 1 до 4. Номер определяет, какая птица должна чирикать.
В первой части игры воспроизводится чириканье птиц. Этот кадр управляется клипом "actions", который анализирует номера в последовательности и сообщает программе, какая птица когда должна петь.
В следующей части игра ждет, когда пользователь начнет щелкать по птицам. После каждого щелчка проверяется, правильно ли была выбрана птица. Таким образом программа все время следит за пользователем, ожидая момента, когда он ошибется. Если игрок сделал все правильно, в последовательность добавляется новая мелодия, и все начинается заново.
Игра начинается с создания произвольной последовательности из пяти цветов, которая хранится компьютером в тайне до конца игры.
При каждой попытке игроку предоставляется пять новых пустых мест, которые нужно заполнить. В дополнение к ним справа появляется кнопка Done (Готово). На рис. 14.4 показано, что видит игрок в начале игры.

Рисунок 14.4 Игра начинается с того, что отображаются пять свободных пустых мест и кнопка Done
Игрок может щелкнуть по любому пустому месту, чтобы изменить его цвет. Цвет изменяется в соответствии с шестью вариантами: пятью различными цветами и пустым местом.
После того как игрок указал цвета для пяти мест, он может щелкнуть по кнопке Done, чтобы получить результат. Появление белого камешка свидетельствует о правильно расположенном цвете, черного - о правильном цвете, помешенном не на свое место.
Затем под имеющимся рядом отображаются следующие пять свободных мест вместе с кнопкой Done. На рис. 14.5 показано, как выглядит игра после нескольких шагов.

Рисунок 14.5 Так выглядит игровое поде после нескольких попыток пользователя
Вся игра происходит в одном кадре. Сначала на рабочем поле нет никаких элементов.
Отверстия и колышки - отдельные клипы, они помешаются на рабочее поле с помощью кода, что избавляет вас от необходимости размещать каждый клип и присваивать ему имя. Вместо вас всю работу выполнит программа.
Когда игрок перетаскивает колышек в новое отверстие, код проверяет, какой ход был сделан: верный или ошибочный. Во-первых, пользователь должен переставить колышек на пустое место, через одно отверстие от текущего. Затем необходимо, чтобы в отверстии, через которое "перепрыгивает" игрок, находился колышек. Если ход удовлетворяет этим условиям, он считается верным. Колышек, через который "перепрыгнули", удаляется с доски.
Решетка представляет собой серию клипов, созданных с помощью Action-Script. Когда пользователь щелкает по блоку, он удаляется из решетки после того, как отмечен его цвет. Потом каждый из его четырех соседей подвергается проверке, не того же ли он цвета. Если не того же, удаленный блок восстанавливает свой исходный цвет.
Метод удаления блоков является рекурсивным. Каждый сосед выделенного курсором блока проверяется, какого он цвета. Если того же; проверяется каждый его сосед, и т. д. Этот рекурсивный метод в конце концов находит блок, который не имеет соседей того же цвета, и рекурсия заканчивается.
Если вы не вполне уверены, что понимаете, как работает эта рекурсия, посмотрите пример шаг за шагом. Например, пользователь щелкнул по красному блоку. Из четырех его соседей блок сверху и блок справа тоже красные. Возьмите блок сверху. Среди его соседей нет красных блоков. Возьмите блок справа. Блок снизу от него тоже красный. Возьмите этот третий красный блок. Среди его соседей нет красных блоков. Таким образом, блок, по которому пользователь щелкнул, удаляется. Удаляется также блок сверху, блок справа и блок снизу от блока справа.
Хотя игра не определяет, сделал ли пользователь все возможное, она присуждает очки. Лучший способ определения очков в подобной игре -это экспоненциальная система присуждения очков. Таким образом, если удаляется группа из двух блоков, игрок получает 4 очка: 2 раза по 2. Если удаляется группа из 3 блоков, игрок получает 3 раза по 3, или 9 очков. Если же удаляется группа из 4 блоков, игрок получает 4 раза по 4, или 16 очков.
Эта система подсчета очков поощряет игрока находить большие группы блоков. Например, удаление 10 групп по 2 блока принесет пользователю 40 очков (2 раза по 2 будет 4, 10 раз по 4 будет 40). Удаление же одной группы из 20 блоков приносит пользователю 400 очков (20 раз по 20). Пользователь должен не только искать большие группы блоков, но пытаться сам их создавать, вытаскивая маленькие группы таким образом, чтобы большие группы пришли в соприкосновение и сформировали еще большую группу.
Рекурсивные блоки
Исходный файл: Blocks.fla
Я встречал эту игру в разных вариациях под разными названиями. Основная идея ее в том, что экран заполнен большой решеткой, состоящей из цветных блоков. Игрок может нажать на блок, чтобы удалить его из решетки. Но чтобы удаление блока стало возможным, он должен иметь сверху, снизу или рядом соседний блок того же цвета.
Когда игрок нажимает на доступный для удаления блок, он убирается. К тому же, убирается и соседний блок того же цвета. Все соседи одного цвета с удаленным блоком удаляются тоже. Таким образом, связанная область блоков одного цвета может быть удалена нажатием на любой из блоков этой области.
После удаления группы блоков их верхние соседи спускаются вниз на освободившиеся места. Если какая-нибудь колонка блоков оказывается совершенно пустой, решетка сдвигается влево, чтобы заполнить свободные места.
На рис. 14.8 показано начало игры. В добавление к одному из четырех цветов я поместил на каждый блок маленький рисунок, соответствующий цвету блока. Это облегчает распознавание блоков на черно-белом рисунке. Единственный способ действительно понять игру- это сыграть в нее, поэтому сделайте это прямо сейчас, прежде чем продолжать читать дальше.

Рисунок 14.8 Игра "Рекурсивные блоки" начинается со случайной решетки цветных блоков
Создание кода
Код игры целиком расположен в первом кадре основной временной шкалы, начинается он с установки целого набора переменных. Эти числа определяют положение различных элементов на рабочем поле при их создании. Вместо того чтобы распределять эти переменные по всему коду, я собрал их в начале программы - так их будет проще найти и изменить.
Последовательность решения задается с помощью пяти случайных чисел и хранится в массиве solution. В переменной row хранится номер попытки. Для начала игры вызывается функция createRow.
initGame();
stop() ;
function initGame() {
// Определяется расположение и расстояние между элементами.
topRowLoc = 60;
leftColLoc = 280;
roghtColLoc = 390;
horizSpace = 21;
vertSpace = 23 ;
solutionx = 336;
solutiony = 320;
// Создается произвольная последовательность решения
solution = new Array();
for(i=0;i
solution.push(int(Math.Random()*5)) ;
}
// Инициализируются переменные.
rows = new Array();
row = 0;
// Устанавливается первый ряд.
createRow();
}
В начале каждой попытки функция createRow создает пять пустых мест и определяет их положение. Вдобавок устанавливается новый клип done, который располагается справа (рис. 14.4).
function createRow() {
// Создается новый ряд из пяти пустых мест.
attachMovie("rock","rock"+row+"-"+i,row*10+i);
clip = _root["rock"+row+"-"+i];
clip._x = leftColLoc + i*horizSpace;
clip._y = topRowLoc + row*vertSpace;
clip, active = true;
}
// Создается кнопка Done.
attachMovie("done","done",1000);
_root.done._x = rightColLoc+20;
_root.done._y = topRowLoc + row*vertSpace;
}
Когда игрок щелкает по кнопке Done, вызывается функция doneGuess. Сначала пять кнопок в текущем ряду становятся неактивными. В функции createRow свойству active каждого клипа было присвоено значение true. Теперь же этому свойству присваивается значение false (1). Код, прикрепленный к каждой кнопке, с помощью этого свойства определяет, можно ли щелкнуть по кнопке или нет.
В массиве temp содержатся номера каждого цвета последовательности (2). Например, если даны два первых цвета, один четвертый и два пятых, массив будет выглядеть следующим образом: [2,0,0,1,2].
Следующий цикл проверяет, сколько цветов точно совпадают с предопределенным расположением (3). Если были найдены совпадения, числа в массиве temp уменьшаются. То есть теперь в этом массиве отображаются те цвета, совпадения с которыми еще надо найти.
Следующий цикл проверяет несовпавшие цвета в последовательности игрока и определяет, какие из этих цветов находятся в массиве temp (4). Подсчитав, можно выяснить, сколько цветов правильно угаданы, но помешены не на свое место.
Следующие два цикла создают белые и черные камешки, которые будут соответствовать числу правильно угаданных цветов и числу угаданных цветов, расположенных не на своем месте (5).
Кнопка Done удаляется, так что теперь она не будет появляться в каждой строке (6). Когда пользователю дается следующая попытка, создается новая кнопка Done.
В конце функции проверяется, совпадают ли все пять цветов или нет (7). Если да, то ролик переходит к кадру "win". В противном случае код проверяет, была ли эта попытка десятой (последней), и если так, ролик
Почти весь код находится в одном кадре основной временной шкале. Он начинается с создания экземпляров клипов "peg" и "hole" и их размещения на рабочем поле. С помощью оператора if создаются необходимые для игры отверстия. Также код проверяет, во все ли отверстия, кроме одного в центре, вставлены колышки.
В конце функции переменной maxHole присваивается значение, равное количеству всех отверстиях. Эта' переменная будет использоваться в тех функциях, где необходимо выяснить, все ли клипы удовлетворяют определенным условиям.
initGame();
stop();
function initGame() {
// Определяем постоянное расположение клипов.
holeSpace =30;
puzzleLeft = 160;
puzzleTop = 80;
// Просматриваем все отверстия создаем в них колышки.
i = 0;
for(y=0;y
for (x=0;x
// Проверяем, должен ли быть создан колышек.
// Если да, создаем его.
if (((у < 3) or (у > 5)) and ((х < 3) or (x > 5) continue;
// Добавляем и размещаем новое отверстие. attachMovie("hole", "hole"+i, i);
_root["hole"+i]._x = x*holeSpace + puzzleLeft;
_root["hole"+i]._y - y*holeSpace + puzzleTop;
II He добавляем колышек в центральное отверстие,
if ((x != 4) or (у != 4)) {
// Добавляем и размещаем
// новое отверстие.
attachMovie("peg","peg"+i,100+i);
_root["peg"+i]._x = x*holaSpace + puzzleLeft;
_root["peg"+i]._y = y*holaSpace + puzzleTop;
}
i++;
}}
// Запоминаем количество колышков.
maxHole = i;
}
Когда игрок щелкает по колышку, на самом деле он щелкает по кнопке, расположенной внутри клипа. Оба действия, "press" и "release", передаются функциям в основной временной шкале. Функция dragPeg вызывается действием "press". Эта функция сохраняет положение колышка в переменных pegх и pegу, а затем разрешает перемешать колышек. Также она использует функцию swapDepths, чтобы колышек отображался поверх всех остальных.
function dragPeg(peg) {
// Запоминаем исходное положение колышка,
pegх = peg._х; pegу = peg._у;
// Размещаем колышек поверх остальных,
peg.swapDepths(2000);
// Разрешаем программе Flash перемещать клип.
startDrag(peg, true);
}
Создание блоков происходит в функции startGame. Функция совершает циклы по 20 горизонтальным колонкам и 12 вертикальным рядам и создает 240 блоков. Каждый блок - это новый экземпляр клипа "block", созданного функцией attachMovie. Кроме того, чтобы оказаться в нужном месте рабочего поля, каждый блок обладает свойствами x и у, таким образом, позже он сможет определить свое положение.
Выбирается случайное число от 1 до 4, и клип с блоком отправляется к этому кадру.
function startGaine () {
// Переходим к кадру игры.
gotoAndStop("Play");
score = 0;
// Создаем решетку из блоков,
level = 0;
for(var x=0;x
forlvar y=0;y
mc = _root.attachMovie("block","block "+x+" "+y,level);
mc._x = 20*x + 85;
mc._y = 20*y + 60;
mс.x = x ;
mс.у = у ;
// Выбираем случайный цвет.
mc.gotoAndStop(Math.ceil(Math.random()*4));
level++;
}}
}
Когда пользователь шелкает по блоку, чтобы выбрать его, короткий сценарий посылает свойства х и у блока функции, чтобы программа могла решить, какие действия предпринять
on(release) {
_root.clickBlock(x,у);
}
Функция clickBlock определяет цвет блоков и хранит его в переменной Затем блок удаляется (точнее, его клип переходит к пустому кадру). Функция testNeighbor вызывается четыре раза, один раз для каждого соседа. Функция возвращает количество подходящих соседей, найденных в данном направлении. Если, например, сосед сверху того же цвета и три его соседа тоже, возвращается число 4. Добавляя это число к переменной n, вы получаете полное количество блоков в группе.
Если обнаружено, что группа состоит более чем из одного блока, вызываются функции collapseDown и collapseAcross, чтобы удалить все блоки группы. В противном случае выделенный блок возвращается к прежнему цвету, и кажется, что ничего не произошло.
// Произошел щелчок по блоку,
function clickBlock(x,у) {
Обратите внимание на ключевое слово var перед описанием переменной с. Это делает с локальной переменной, существующей только в функции clickBlock. Любое использование с за пределами функции clickBlock будет отнесено к самостоятельной переменной. При применении рекурсивных техник, когда функция вызывает саму себя или похожую функцию, лучше использовать локальные переменные, чтобы переменные не наступали друг другу на пятки, когда программа движется от функции к функции.
Код этого ролика делится на две части. Первая часть - набор функций, расположенных в первом кадре ролика. Вторая часть находится в клипе "playback actions", который управляет воспроизведением мелодий в кадре "play". Небольшие фрагменты кода есть и в других местах. Функции, используемые в этой ролике, расположены в первом кадре основной временной шкалы. Они инициализируют переменные игры, отвечают за реакцию на щелчки мышью и воспроизводят мелодии.
Сначала в игре вызывается функция initGame, которая устанавливает все переменные. Эта функция вызывается в начале игры всегда и в конце, если игрок хочет сыграть заново, то есть снова переходит к первому кадру.
Функция initGame очищает массив notes, затем вызывает функцию addNextNote, чтобы поместить в этот массив случайное число. Также она указывает, что счет игры должен отображаться равным 0.
initGame();
stop();
function initGame() {
// Очищаем массив сообщений,
notes = new Array();
scoreDisplay = "Score: 0";
// Добавляем первое сообщение.
addNewNote();
}
Функция addNextNote случайным образом выбирает номер кадра от 1 до 4 и помещает его в массив notes.
function addNextNote() {
// Выбираем случайное число из диапазона от 1 до 4.
r = int(Math.Random()*4+1);
// Добавляем число в массив,
notes.push(r);
}
Остальные функции этой игры используются позже. Функция startRepeat вызывается тогда, когда игрок прослушал пение птиц и должен щелкать по их изображениям, чтобы воспроизвести соответствующие мелодии.
Переменная repeatNum отслеживает, по какому элементу должен щелкнуть игрок. Изначально ее значение равно 0, а затем оно изменяется каждый раз, когда пользователь щелкает по птице.
function startRepeat() {
// Определяем, по какому элементу
// должен теперь щелкнуть пользователь.
repeatNum = 0;
// Переходим к кадру, где размещены кнопки.
gotoAndPlay("repeat");
}
Функция clickBird вызывается теми кнопками, которые спрятаны за изображениями птиц; ей передается номер элемента, по которому щелкнули. Сначала функция проигрывает анимацию птицы и соответствующую анимацию пения. Затем сравнивает сообщение со следующим сообщением в списке. Если они совпадают, значит, игрок правильно выбрал птицу, и значение переменной repeatNum увеличивается. Если это было последнее сообщение, игра переходит к кадру "correct". В противном случае функция ждет, пока не выберут следующее сообщение. Если сообщение не совпадает с предопределенным, ролик переходит к кадру "wrong", и игра заканчивается.
создать простую игру под названием
Цель ролика - создать простую игру под названием "Дедукция". Игроку предоставляется 10 шансов, чтобы угадать последовательность. После каждого варианта игроку выдается результат угадывания.
Цель проекта - создать компьютерный вариант игры "Йога" (рис. 14.7). Игрок щелкает мышкой и перемешает колышки. Неверный ход сделать нельзя, а правильный автоматически удаляет элемент, через который "перепрыгнули".
Цель этого проекта в том, чтобы создать игру, дающую лишь основное представление об игровом процессе. В добавление к уже обсуждавшимся общим правилам нужно сделать еще простую систему подсчета очков. Однако, не будет предпринято никакой попытки определить, когда игра заканчивается. Предложения, как можно это сделать, даны в конце этой главы.
Другие возможности
Суммы, указанные в функции winnings, я выбрал, руководствуясь обычными правилами покера. Однако вы можете указать другие числа в зависимости от той суммы, которую хотите переводить на счет виртуального казино или игрока.
Можно сделать и так: когда на счету игрока не остается денег, переходить, например, к кадру game over.
Еше одна вариация игры - позволить игроку ставить от одного до пяти долларов за игру. Таким образом, игрок ставит меньшую сумму, когда чувствует, что ему не везет, и большую - в других случаях.
Эта игра очень хороша для изучения языка ActionScript, но она разочарует игроков в двадцать одно, играющих на деньги. Поэтому для хороших ActionScript-профаммистов далее представлено руководство, как добавить некоторые возможности этой игры, которые были опущены.
Легче всего добавить возможность раздачи только двух карт. Для этого нужно создать кнопку Double (Удваивание ставки) в кадре с меткой "Player". Когда игрок щелкнет по ней, ему дадут еще одну карту, ставка еще раз будет вычтена из суммы наличных денег, и игра перейдет к раздающему. Однако прежде следует убедиться, что игрок не взял какие-либо дополнительные карты, поскольку такая раздача возможна только тогда, когда у игрока на руках первые две карты.
Возможность страхования создать немного сложнее, так как при этом надо написать еше одну "ветвь" программы. Страхование возникает тогда, когда раздающему показывается туз. В этом случае игрок может застраховаться от того, что у раздающего будет 21, на сумму, обычно равную ставке. Если было взято страхование, и у раздающего 21 очко, игра заканчивается. Игрок теряет исходную ставку, но получает страховую сумму.
Разделение - сложное дополнение к игре. Если у игрока две карты одного достоинства, например две девятки, тогда ему может быть разрешено разделить карты на два расклада, каждый из которых будет начинаться с девятки. Следовательно, чтобы можно было хранить карты игрока в одном массиве playerHand, вы должны создать массив из массивов. В большинстве случаев в таком массиве playerHand содержится один массив, который отражает расклад на одной руке. Если игрок разделит карты, то в массиве будут содержаться два массива. Игроку обычно позволяется разделять карты несколько раз, таким образом, в массиве playerHand может содержаться три, четыре и более массивов. Затем нужно сыграть с каждым раскладом игрока. Вы понимаете, насколько это усложняет каждую часть игры. Игрок может выиграть, проиграть или сыграть в ничью по нескольким или всем своим раскладам.
Игру можно сделать значительно проще, если вы разрешите игроку переворачивать колоду уже открытых карт и смотреть карты столько раз, сколько он захочет. Вы можете сделать это, опознавая, когда массив deck пуст, и помещая каждую карту из массива stack обратно в массив deck.
Кроме этого пасьянса вы можете создать много других. В моей коллекции более 200 вариантов подобных игр. Большинство из них требует вытаскивания карт и перекладывания из стопки в стопку. Это делает код гораздо более сложным, но не невозможным для опытного программиста.
Игра в очко, или двадцать одно
Исходный файл: Blackjack.fla
Двадцать одно - еще одна популярная карточная игра в казино, которую легко можно перенести на компьютер. Раздающий карты следуют определенному набору правил, следовательно, можно написать программу, которая будет имитировать действия раздающего.
Игровой автомат
Исходный файл: Slotmachine.fla
Игровой автомат - игра функционально простая, но с довольно сложным интерфейсом. Игрок просто щелкает по рычагу игрового автомата и ждет результата. Автомат сам выполняет всю оставшуюся работу.
На рис. 15.1 показан фрагмент ролика Slotmachine.fla. Рычаг справа единственный элемент, который будет реагировать на действия игрока. Когда игровой автомат останавливается, в трех окошках отображаются картинки.
К сведению
Если вы посмотрите на ролик, который приводится в качестве примера, то увидите, что фон игрового автомата на самом деле располагается на переднем плане. Три окна - это "дырки" в изображении, сквозь них видно, как проигрывается анимация вращения, а также видны символы на барабанах.
Вы можете указать действия, которые будут совершаться, если деньги на счету игрока закончатся. Можно проверять это условие и, если оно оказывается истинным, переходить к другому кадру. Можно сообщить игроку, что игра окончена, либо предоставить еще 100 долларов, чтобы игрок сыграл еще раз.
К каждой кнопке Hold/Draw прикреплен собственный фрагмент кода. Для первой кнопки он выглядит следующим образом:
on (press) { holdDraw(0);}
Цифра 0 сообщает функции holdDraw, что действие производится с нулевой картой, для остальных четырех кнопок вместо нуля стоят числа от 1 до 4.
Хотя первый кадр ролика сразу же вызывает функцию startGame (см. раздел "Создание кода"), второй кадр должен вызывать функцию startDeal. Просмотрите ролик, приведенный в качестве примера, чтобы самостоятельно изучить, как это реализовано.
Основная временная шкала этого ролика - самая сложная из всех игр, рассмотренных в этой книге. Поэтому важно просмотреть ролик на Web-сайте, чтобы получить четкое представление о том, что и где расположено.
Также необходимо создать текстовые поля, в которых будут отображаться сумма очков игрока и раздающего, ставка, сумма наличных и результат.
Кнопка New на экране имеет простой сценарий и сначала вызывает clearGame, а потом startGame. Это перезапускает игру в любой удобный пользователю момент.
on (press) {
clearGame();
startGame();
}
Пасьянс "Пирамида"
Исходный файл: Pyramicd.fla
Пасьянс "Пирамида" не так популярен, как обычный пасьянс, и не так сложен; однако, ему легко научиться и он очень затягивает. На рис. 15.7 . представлено начало игры.

Рис. 15.7 В пасьянс "Пирамида" играют с помощью пирамиды из 28 карт и остальной колоды
Играть можно любой полностью открытой картой. Если часть карты закрыта другой картой пирамиды, играть этой картой можно только в том случае, если закрывающую ее карту удалить. Удалить карту игрок может только в том случае, если найдет подходящую ей другую карту, чтобы сумма их значений равнялась бы 13. Например, 10 и 3 или 6 и 7 могут составить пару. Туз имеет значение 1, валет значение 11, дама 12 и король 13. Это значит, что только король может быть выбран сам по себе, без второй карты.
Цель, естественно, в том, чтобы убрать из пирамиды все карты. Оставшиеся 24 карты колоды помешены под пирамидой, и за один ход можно перевернуть одну карту. Любая перевернутая карта может быть выбрана вместе с картой из пирамиды так, чтобы составить в сумме число 13.
Попробуйте поиграть в этот пасьянс. Вам придется отложить книгу, поскольку понадобится потратить какое-то время, чтобы окончить игру.
Подготовка ролика
В этом ролике используются три ключевых библиотечных эталона, все остальное - элементы фона. Первый эталон - рычаг, в его первом кадре находится кнопка, по которой может щелкнуть игрок. Остальная часть клипа - анимация рычага, показывающая, как нажали рычаг.
Клип "spin" начинается с пустого кадра, где он "ждет", пока игрок не щелкнет по рычагу. Кадр прозрачный, так что сквозь него виден клип "symbols".
В остальных кадрах клипа "spin" находится размытая анимация. За изображениями, показанными на рис. 15.2, расположен белый непрозрачный фон, закрывающий клип "symbols" во время вращения колес.
В клипе "symbols" находятся семь кадров, во всех содержатся разные символы. В ролике Slotmachine.fla это изображения желудя, яблока, листа, бревна, луны, солнца и лисы.
Основной библиотечный элемент в данной игре - колода карт, то есть клип с 54 кадрами. Первый кадр отображает пустой контур карты. Во втором кадре содержится рубашка карты. Кадры 3-54 показывают различные карты колоды. Каждый кадр имеет такое же имя, какое используется в коде для идентификации карт. Например, "c1" - туз треф и "h11" -валет червей.
Просмотрите ролик Videopoker.fla и вы увидите, что для клипа "deck" выделена целая папка библиотеки, заполненная графическими изображениями. Это упрощает повторное использование элементов для разных карт.
Ролик составлен из пяти экземпляров клипа "deck" (колода), которые называются "card0", "card1", "card2", "card3" и "card4". В первом кадре
нужна только кнопка "Deal" (Раздать), которая отображается также и в третьем кадре.
Во втором кадре находится кнопка "Draw" (Выигрыш), а под каждой картой - кнопка "Hold/Replace" (Оставить/Поменять).
В отличие от видеопокера на руках может быть от двух до 11 карт. Для каждого расклада создаются 11 экземпляров клипов, имена которых изменяются от "player0" до "player10" и от "dealer0" до "dealer10". Кадры клипа "deck" - пусты. Следовательно, когда вы поместите клип на рабочее поле, вы не увидите ничего, кроме меток, которые устанавливаются программой Flash для клипов по умолчанию. На рис. 15.5 показаны все 22 метки.

Рисунок 15.5 Все карты представлены в виде маленьких кружочков, меток клипа, так как на данный момент-карты не видны
В этом ролике сложная основная временная шкала. Каждая метка представляет собой различный этап игры. На рис. 15.6 показана шкала в момент, когда видна большая часть меток.

Рисунок 15.6 В сложной основной временной шкале игры в очко для каждого шага существует помеченный кадр
В процессе игры указатель текущего кадра передвигается вдоль основной временной шкалы. Каждый ключевой кадр содержит различные функции. Сам код расположен в первом ключевом кадре.
Обязательно просмотрите ролик Blackjack.fla, чтобы самому увидеть, где расположены ключевые кадры и какие функции они вызывают.
Ролик содержит в библиотеке такой же клип "deck", как в игре "Двадцать одно". Ему необходимо присвоить имя в панели Linkage Properties,чтобы он экспортировался вместе с роликом. То же относится и к клипу "outline". ' В игре присутствует только два кадра: кадр "Play" и кадр "Game over". Последний будет использоваться только в редком случае выигрыша. Оба кадра должны содержать кнопку New, чтобы пересдавать карты в любой удобный игроку момент.
Подход
Единственной сложной частью кода в игре является вращение. Осуществить это можно следующим образом: сделать так, чтобы различные картинки прокручивались в окошке снизу вверх. Проблема заключается в том, что картинки должны вертеться так же быстро, как крутятся барабаны в реальном игровом автомате. На большинстве компьютеров программа Flash не может проигрывать ролик с такой скоростью. Вместо этого можно воспользоваться размытой анимацией вращения, которая представляет собой клип, состоящий из нескольких "размытых" кадров. На рис. 15.2 показаны несколько подобных кадров.

Рисунок 15.2 Эти кадры анимаиии создают эффект крутящегося барабана при быстром воспроизведении
В каждом из трех окон будет отображаться копия клипа spin. Когда придет время вращения барабана, всем трем клипам будет сообщаться о воспроизведении, а также передаваться точное число вращений. Эти значения будут различными для каждого клипа, так что барабаны будут останавливаться не одновременно.
Просмотрите ролик Slotmachine.fla, чтобы увидеть, как крутятся барабаны и как они последовательно останавливаются.
Первое, что необходимо программе, - это перетасованная колода карт, которая будет представлять собой массив с символьными данными, например "h7", что означает семерка червей. Четыре масти представлены буквами "с", "d", "h" и "s". Туз обозначен "1", то есть «c1" означает туз треф, а валет, дама и король обозначены цифрами "И", "12" и "13" соответственно.
Создать упорядоченную колоду карт просто, совсем другое дело - создание перетасованной колоды. Для этого вы берете упорядоченный массив и, выбирая из него случайным образом элементы, один за другим помешаете их в новый массив.
Затем первые пять карт в массиве отображаются на экране. Под каждой картой располагается кнопка. Один щелчок мыши по ней переворачивает карту, так что будет видна рубашка карты. Второй щелчок возвращает карту в исходное положение на тот случай, если игрок передумал.
Когда игрок будет удовлетворен своим выбором, он щелкает по кнопке Draw (Поменять). Те карты, которые были выбраны длят замены, замешаются следующими картами из перетасованной колоды.
Самый сложный фрагмент программного кода нужен для конечной фазы игры. Окончательный массив из пяти карт должен быль оценен с точки зрения покера. Вот список возможных вариантов:
• младшая пара - пара карт одного достоинства (десятка или ниже);
• старшая пара - пара валетов, дам, королей или тузов;
• тройка - три карты одного достоинства;
• стрит - пять карт, ранг каждой из которых на единицу превышает ранг предыдущей карты, например восьмерка, девятка, десятка, валет и дама. Туз может располагаться как перед двойкой, так и послекороля;
• флэш - пять карт одной масти;
• фул хаус - пара и три карты одного достоинства;
• каре - четыре карты одного достоинства;
• стрейт флэш - пять карт одной масти, ранг каждой из которых на единицу превышает ранг предыдущей карт;
• роял флэш - стрейт флэш с десяткой, валетом, дамой, королем и тузом.
Для того чтобы определить, удовлетворяет ли набор карт вышеуказанным критериям, необходимо проанализировать массив с картами несколькими способами.
После того как будет определена ценность карт, останется сделать последний шаг - сопоставить ее с суммой выигрыша и увеличить наличность игрока.
Как и в видеопокере, здесь есть массив deck, в котором содержится перетасованная колода карт. Разница заключается в том, что в этой игре в массиве находятся шесть колод. В игре в очко такой массив называется shoe.
Как для игрока, так и для раздающего создается массив, в котором представлены карты, имеющиеся на руках. Вам нужно будет подумать насчет первой карты раздающего, так как она не должна быть видна до тех пор, пока игрок не закончит набирать карты.
В отличие от видеопокера оценка расклада в этой игре проста. Единственная сложность: туз может стоить как одно, так и 11 очков. Однако, так как два туза дадут 22 очка, второй туз никак не может стоить 11. То есть все, что нужно, - определить, есть ли на руках туз, подсчитать, что он равен единице, а затем добавить 10, если при этом на руках не будет перебора. Например, расклад с тройкой, девяткой и тузом рассматривается как 13 очков, потому что если считать, что туз стоит 11, то на руках окажется 23 очка, то есть перебор.
Мы используем такую же колоду, как и в игре "Двадцать одно". Игра начинается с тасовки карт и выстраивания пирамиды. Остальные карты помешаются стопкой мастью вниз внизу экрана. Игрок может щелкнуть, по верхней карте в стопке, и карта отобразится мастью вверх в соседней стопке карт, которая изначально была пустой. Каждый щелчок по стопке карт, лежащих мастью вниз, добавляет одну карту к стопке карт, лежащих мастью вверх.
Игрок может выбрать любую незакрытую карту из пирамиды или из стопки карт с открытой мастью. Выбранная карта выделяется рамкой.
Когда игрок щелкает по следующей карте, она сравнивается с первой, чтобы узнать, составит ли она с ней вместе 13 очков. Если да, обе карты удаляются. Если при этом одна из карт находится в стопке карт мастью вверх, то лежащая под ней карта открывается.
Определить, открыта ли какая-то карта в пирамиде, можно, пройдя циклом по всем картам в пирамиде и выясняя, присутствует ли на месте одна
из двух карт, которые должны закрывать данную. Например, вторая карта в третьем ряду должна быть закрыта второй и третьей картой в четвертом ряду. Если какая-нибудь из них на месте, карта не может быть выбрана. Когда карта удаляется из стопки открытых карт, становится видна предыдущая открытая карта. Это означает, что вам нужно следить за стопкой открытых карт, помещая их в массив, как только они оказываются перевернутыми.
Особым случаем является король. Выбранный король немедленно удаляется как из колоды карт с открытой мастью, так и из пирамиды, если, конечно, выбранный король был открыт.
Создание кода
Большая часть кода для этой игры находится в основной временной шкале. Однако сначала разберем те фрагменты кода, которые относятся к клипам.
В ролике Slotmachine.fla под клипом с рычагом размещена кнопка. К ней прикреплен простой сценарий, который вызывает функцию pull, находящуюся в основной временной шкале.
on (release) {
pull();
}
В клипе "spin" содержатся два небольших сценария. Команда stop () находится в первом .кадре. Сценарий, который уменьшает значение счетчика numTimes на единицу, располагается в последнем кадре. Если значение счетчика равно нулю, сценарий переходит к первому кадру ролика и сообщает об этом функции в основной временной шкале. В противном случае клип снова возвращается ко второму кадру.
numTimes--;
if (numTimes
gotoAndStop(l);
_root.spinDone(_name);
} else {
gotoAndPlay(2); }
Большой фрагмент программы в основной временной шкале определяет, сколько денег выиграл пользователь, если выиграл вообще. Программа начинается с того, что случайным образом выбирает кадр для трех символов и предоставляет игроку $100, на которые он может играть в этой виртуальной игре.
initGame() ;
stop();
function initGame() {
// Случайным образом выбираем кадры для трех символов,
for (i=l;i
_root["symbol"+i].gotoAndStop(randomSymbol());
}
// Начинаем со $100.
cash = 100;
showCash();
}
Вместо того чтобы отображать сумму, имеющуюся у игрока, просто цифрами, следующая функция помещает перед ней знак доллара и добавляет переменную cash в displayCash. Эта переменная связана с текстовым полем на рабочем поле.
// Отображаем сумму в долларах,
function showCash() {
cashDisplay.= "$"+cash;
}
Когда игрок щелкает по рычагу, происходит несколько событий. Сначала из суммы наличных денег игрока вычитается $1. Затем клип "arm' переходит ко второму кадру, то есть показывается, что рычаг переходит в нижнее положение. Затем все три клипа "spin" начинают проигрываться. Каждому клипу сообщаются различные значения переменной numTimes - 8,6 и 4 - то есть первая анимация будет проигрываться восемь раз, вторая - шесть и третья - четыре. Также здесь определяется результат каждого вращения, устанавливаются клипы "symbol", хотя они скрыты за непрозрачными анимациями "spin" до тех пор, пока эти анимации не будут проиграны.
Большая часть кода содержится в первом кадре основной временной шкалы. Начинается она с того, что игроку предоставляется 100 долларов.
startGame();
stop () ;
// "Выдаем" исходную сумму,
function startGame() {
cash = 100;
}
Как и в предыдущем проекте, перед суммой наличных денег игрока отобразите знак "$".
// Отображаем сумму наличных со знаком доллара,
function showCash() {
cashDisplay = "$"+cash;
}
Раздача карт начинается с того, что у игрока изымается один доллар. Каждая раздача производится из новой колоды, состоящей из 52 карт. Функция f irstDraw берет первые пять карт, а функция showCards помешает клипы соответствующих карт на рабочее поле.
// Сдача карты,
function startDeal() {
// Уменьшаем сумму наличных денег.
cash--;
showCash();
// Перетасовываем карты и снова сдаем их.
createDeck();
f irstDraw();
showCards(); }
Создание полностью произвольной перетасованной колоды включает в себя два шага. Первый - создание упорядоченной колоды. Это осуществляется путем циклического просмотра всех мастей и всех рангов карт и для каждой комбинации добавляется соответствующий элемент массива.
Затем программа случайным образом выбирает карты из упорядоченной колоды и помещает их в другой массив. Когда массив заполняется, а предыдущий массив оказывается пустым, у вас получается перетасованная колода карт.
// Создаем перетасованную колоду,
function createDeckO {
// Создаем упорядоченную колоду,
suits = ["с","d","s","h"];
temp = new Array();
for(suit=0; suit
for (num=l; num
temp.push(suits[suit]+num);
}
// Случайным образом выбираем карты,
// пока колода не будет полностью перетасована.
deck = new Array();
while (temp.length > 0) {
r = int(Math.random()*temp.length),
deck.push(temp[r]);
temp.splice(r,1); }
Функция firstDraw берет пять карт из колоды и помешает их в массив cards, а также создает небольшой массив hold, в котором хранятся имена тех карт, которые игрок хочет оставить.
Первый кадр вызывает функцию initGame , но после нее не идет команда stop (), так как указатель должен двигаться и перейти к кадру "shuffle".
initGame();
Функция initGame определяет исходную сумму наличных денег игрока.
function initGame() {
cash = 100;
showCash();
}
Функция createDeck похожа на одноименную функцию, используемую в видеопокере, но здесь она шесть раз добавляет каждую карту, чтобы создать шесть колод карт.
Один из недостатков использования шести колод состоит в том, что программе требуется время для, их перетасовки. Следовательно, кадр "shuffle" появляется перед ключевым кадром, вызывающим функцию createDeck. Поэтому слово "shuffle" (Идет перетасовка колоды) появится на экране прежде, чем код начнет тасовать карты. Следовательно, игрок не должен удивляться, почему его компьютер вдруг "завис".
// Создаем перетасованную колоду карт,
function createDeck() {
// Создаем упорядоченную колоду.
suits = ["с", "d", "s", "h"];
temp = new Array();
for (i=0; i
for (suit=0; suit
for (num=1; num temp.push(suits[suit]+num);
}}}
// Карты выбираются случайным образом до тех пор, пока
// колода не будет перемешана,
deck = new Array();
while (temp.length>0) {
r = int(Math.random()*temp.length) ;
deck.push(temp[r]);
temp.splice(r,1);
}}
В функции initHand создаются массивы playerHand и dealerHand. Переменной showDealerFirstCard присваивается значение false, по умолчанию делается ставка в пять долларов.
// Инициализируем массивов расклада и определяем сумму ставки,
function initHand() {
playerHand = new Array();
dealerHand = new Array();
showDealerFirstCard = false;
bet = 5;
showBet();
}
Когда игрок щелкает по кнопке Add to bet (Повысить ставку), вызывав функция addToBet, которая повышает ставку на пять долларов и не позволяет сделать ставку, превышающую 25 долларов.
// Функция увеличивает ставку игрока вплоть до 25 долларов,
function addToBet() {
bet += 5;
Практически весь код находится в главной временной шкале. Он начинается с функции "startGame". После того как создана новая, перетасованная, колода, создается семь рядов карт (10). Первый ряд содержит» одну карту, второй - две и т.д.
Каждая карта помешается на свое место в соответствии с рядом и местом в ряду (11). К тому же масштаб каждой карты уменьшен на 50%, поскольку колода, использованная в игре "Двадцать одно", в два раза больше по размеру той, что необходима для этой игры (12).
Значение карты берется из массива deck (13). Оно соответствует метке кадра внутри клипа "deck". Это значение сохраняется в свойстве value клипа, после чего клип отправляется в соответствующий кадр. В свойствах клипа row и col хранится позиция клипа в пирамиде (14).
Затем вы создаете клипы для стопок карт мастью вниз и мастью вверх (15). Клип для карт мастью вниз отправляется в кадр "back", показывающий изображение рубашки карты. Другая стопка остается в первом кадре, который пуст.
Переменная firstcard установлена как undefined (16). Эта переменная содержит значение первой карты в паре, выбираемой самим игроком. Массив stack используется для слежения за судьбой карт из стопки мастью вверх. В случае, когда карта из этой стопки используется, должно быть отыскано значение предыдущей выбранной карты.
В заключение должен быть создан экземпляр клипа рамки (17). В начальный момент он помешается за пределами видимости.
startGame();
stop();
function startGame() {
// Тасуем колоду.
createDeck();
(10)// Выстраиваем карты в пирамиду,
level = 0;
for(row=0;row
for(i=0;i
// Создаем новый клип.
mc = _root.attachMovie("Deck","card"+level,level);
(11)// Задаем его расположение.
mc._x = i*60-row*30 + 275;
mc. _у = row*30 + 50;
(12)// Задаем масштаб.
mc._xscale = 50;
mc.__yscale = 50;
(13)// Устанавливаем знчение карты,
mc. value = deck.pop();
mc.gotoAndStop(mc.value);
(14)// Запоминаем позицию карты,
mc.row = row;
mc.col = i;
В отличие от многих игровых
В отличие от многих игровых автоматов, в которых используются интересные, но сложные способы для определения ставок и получения

Рисунок 15.1 Простой игровой автомат с рычагом и тремя окошками
выигрыша, этот предельно прост. Игрок щелкает по рычагу, чтобы привести его в действие. Затем барабаны в трех окнах начинают крутиться. Один за другим они будут останавливаться, показывая произвольный элемент (картинку).
Когда все три барабана останавливаются, картинки, оказавшиеся в них, и определяют результат. Выигрыш соответствует тем суммам, которые показаны внизу игрового автомата (см. рис. 15.1).
Эта игра состоит из трех шагов. Первый шаг - игра ждет, пока игрок попросит сдать карты. На втором шаге игрок смотрит на пять карт, которые ему раздали, и решает, какие оставить, а какие - поменять. И последний шаг - раздаются новые карты, и подсчитывается сумма выигрыша. После чего осуществляется переход к первому шагу.
Игра должна представить игроку набор из пяти карт, выбранных случайным образом из перемешанной колоды (рис. 15.3).

Рисунок 15.3 Видеопокер показывает игроку пять карт
Затем игрок может выбрать те карты, которые следует поменять (можно поменять все). После замены программа должна рассмотреть окончательный набор карт и подсчитать, сколько они "стоят".
Наша цель - создать базисный вариант игры в очко, не стремясь реализовать полный набор функций. Некоторые правила в этой игре редко используются, например удваивание ставки, страхование и разделение, но если вы захотите включить их в свою игру, написание кода окажется очень сложной задачей. Оценить наличие таких правил смогут только избранные, поэтому здесь они опущены, чтобы не перегружать книгу лишней информацией.
На рис. 15.4 показан кадр ролика Blackjack.fla. Вы видите, что игрок взял пять карт, которые в сумме дали 18 очков. А раздающий карты взял три карты, их сумма составляет 21.
В этой простой игре игроку и раздающему дается по две карты. Первая карта раздающего остается лежать рубашкой вверх до тех пор, пока игрок не закончит набирать карты. Игрок может брать карты до тех пор, пока у него не окажется двадцать одно очко или более. Затем компьютер "выдает" карты раздающему, пока у того не будет минимум 17 очков.

Рисунок 15.4 Расклад, когда раздающий выиграл, так как у него 21, а у игрока только 18 очков
Если с первыми двумя картами у игрока 21 очко, он сразу же выигрывает и получает дополнительно 50% суммы выигрыша. Если у раздающего получается 21, игра сразу же приостанавливается. Если же так не случилось, то выигрывает тот, у кого на руках большее количество очков, не превышающее 21.
Игрок может контролировать свои ставки (от 5 до 25 долларов), каждый раз повышая ставку на пять долларов.
Цель этого проекта - создание полной версии игры в пасьянс "Пирамида". Программа должна узнавать даже тот редкий случай, когда игрок выигрывает, удаляя все карты из пирамиды. Если игрок чувствует себя в безвыходном положении или текущая партия представляется неплодотворной, он может нажать кнопку и в любое время пересдать карты.
Другие возможности
Возможно, вы захотите создать свои собственные вариации этого ролика. Допустим, реализовать такую идею: пули всегда будут попадать в одну точку экрана. Игрок сможет управлять кораблем с помощью клавиш со стрелками. Например, если игрок нажимает клавишу со стрелкой "влево", то чтобы создать иллюзию перемещения, все астероиды двигаются вправо.
Также можно усовершенствовать игру, предусмотрев уровни и изменив отображение числа столкновений с астероидом. Например, у вас есть некий механизм подсчета этого числа: когда его значение приблизится к максимальной отметке, начнет мигать красная лампочка.
В таких играх, как "Астероид", можно придумать много интересного. Например, время от времени вокруг корабля может летать небольшой НЛО; если игрок его собьет, то заработает дополнительные очки. Зачастую корабль оснащен щитом, который защищает его от определенного количества столкновений. Функция "Гиперпространство" переносит корабль в произвольную точку экрана, а "бомба" взрывает все астероиды, находящиеся на заданном расстоянии от корабля.
Это превосходная игра, в которой начинающий программист ActionScrip может попробовать свои силы и применить все имеющиеся знания. Чем разнообразнее игра, тем лучше.
Есть множество способов усовершенствовать эту игру. У вас может быть несколько кроликов, специальные ягоды, которые на короткое время будут позволять лисе гоняться за кроликом. Через определенные промежутки
времени из центральной области будет выходить новый кролик, а в коридорах лабиринта будут появляться бонусные очки.
Возможно, вам в голову придут и другие идеи, например, сделать так, чтобы кролик был более сообразительным: гонялся за лисой, соперничал с лисой и поедал ягоды. Можно начислять дополнительные очки в конце каждого уровня в зависимости от того, насколько быстро он был пройден.
В этой игре очки не начисляются. Вы же можете добавлять очки за каждую успешную посадку, причем за посадку на труднодоступные посадочные площадки начислять больше обычного. Также можно предоставлять премию за скорость и объем неиспользованного топлива. Добавить уровни к игре очень просто, для этого нужно только нарисовать рельеф. Когда вы исчерпаете все свои идеи, попробуйте изменить код таким образом, чтобы на более высоких уровнях с тем же рельефом корабль имел меньше топлива или была более сильная гравитация.
Эта игра демонстрирует лишь простейшие возможности платформенного скроллера. Она настолько проста, что даже не имеет завершения. Существует несколько возможностей оформить конец игры.
Во первых, вы можете достигать крайней правой точки для окончания игры или уровня. Пространство этой игры относительно невелико, но если сделать его в несколько раз больше, то прохождение до границы уже будет некоторым достижением.
В другом варианте игра оканчивается, когда игрок собрал все орехи. Опять же вы можете сделать пространство игры больше.
Большинство платформенных скроллеров предлагают также избавляться от разных отрицательных героев. Обычно для этого достаточно прыгнуть сверху на такого плохого парня. В существующем варианте игры, если вы запрыгнете на кролика, игра окончится точно так же, как если бы вы пересеклись с ним по горизонтали. Но если вы сможете определить, что лиса падает сверху в момент столкновения с кроликом, то получите сражающуюся лису, которая будет получать дополнительные очки за побежденных кроликов.
Платформенные скроллеры могут быть очень сложными. Они запросто могут включать сотни страниц кода, добавляющих все больше и больше характеристик в игру. У вас же сейчас реализованы лишь самые основные моменты. Используя навыки предыдущих глав, вы вполне можете сколько угодно надстраивать эту игру.
К сведению
В клипе "foreground" находятся текстовые поля, связанные с переменными hits и damage. К сожалению, так как они расположены на первом уровне внутри клипа, они не будут реагировать на изменения значений hits и damage, принадлежащих основной временной шкале. То есть для этих текстовых полей необходимо указать команды типа _root. displayDamage = damage. Для того чтобы избежать недоразумений, эти области были названы displayDamage и displayHits.
Как всегда, убедитесь, что для клипов в библиотеке установлены свойства связи, чтобы они были включены в swf-файл. Свойства связи необходимо установить для астероидов и пуль, потому что до начала игры их нет на рабочем поле.
Я также создал три текстовых поля, отображающих значения переменных gameLevel, lives и score. Эти поля расположены в разных углах экрана, над ними добавлен поясняющий текст.
He забудьте, что нужно присвоить имена связи клипам лисы, кролика и ягоды. Для каждого кадра, в том числе и в небольших клипах, вам понадобится функция stop().
В этом ролике к каждой кнопке Play прикреплена одна строчка кода. Просмотрите каждый из этих сценариев, чтобы понять, к какому кадру переходит ролик или какая функция вызывается.
Обратите внимание, что во всех трех типах ускорителей использовалась одна и та же анимация - thrust animation. Для левого и правого ускорителей клип поворачивался на 90° или на -90°. Размер анимации боковых ускорителей был уменьшен, так как предполагается, что они слабее основного ускорителя.
Клип с лисой содержит три части: "stand", "run" и "jump". В первом кадре содержится команда stop(). В последнем кадре анимации "run" содержится команда gotoAndPlay ("run"). Благодаря этому движение зацикливается.
Клип "acorn" также содержит команду stop О в первом кадре.
Еще один важный момент - это установка центра координат клипов. Он расположен внизу и отцентрирован по горизонтали. На рис 16.9 изображен клип "box" и его центр.

Рис 16.9 Во всех клипах центр находится внизу точно посередине
Космический бой
Исходный файл: Spacecombat.fla
Аркады иногда называют играми на реакцию, так как единственные необходимые здесь навыки - умение быстро реагировать. Это особенно верно для первой игры, "Космический бой".
На рис. 16.1 показан фрагмент ролика Spacecombat.fla: игрок как бы находится внутри космического корабля, навстречу которому летят астероиды.

Рисунок 16.1 В игре "Космический бой" вы - пилот космического корабля, который пытается пролететь сквозь поле астероидов
Луноход
Исходный файл: Moonlander.fla
Вот еще одна классическая игра. Игра "Луноход" была, возможно, второй из когда-то созданных компьютерных игр. Ее первая версия предназначалась для универсальной ЭВМ и была полностью основана на тексте. Каждую секунду компьютер в виде текста выдавал, где в данный момент находится луноход и какова его скорость. По мере снижения лунохода игрок мог вносить коррективы.
С тех пор игра воссоздавалась в различных графических форматах, большинство из которых, как и здесь, использовали вид сбоку (рис. 16.6).

Рисунок 16.6 Луноход снижается, пытаясь приземлиться на одну из приспособленных для этого площадок Задача проекта Цель - создать стандартную игру, в которой корабль должен удачно совершить посадку. Он начинает свое движение вверху экрана, игрок управляет сильным вертикальным ускорителем, расположенным под кораблем, а также более слабыми ускорителями - по бокам корабля.
С течением времени корабль снижается под воздействием гравитации. Игрок не может постоянно пользоваться ускорителями, так как у корабля ограниченный запас горючего.
Задача игрока состоит в том, чтобы корабль в полной сохранности совершил посадку на одну из отведенных для этого площадок. Если он сядет не на площадку или как-то иначе коснется поверхности луны, то произойдет взрыв. В этой игре несколько уровней. В ролике, который приводится в качестве примера, их три, и в каждом отображается различный рельеф. Подготовка ролика Сначала рассмотрим клип "ship". На рис. 16.7 показан полноэкранный вид окна программы Rash в момент, когда выбран клип корабля. В этом клипе несколько кадров с метками: "normal", "up", "left", "right" и "explode".

Рисунок 16.7 Клип "ship" включает следующие кадры: "normal", "up", "left", "right" и "explode"
В первом кадре представлен корабль без включенных ускорителей. Во втором кадре включен главный ускоритель, который поднимает корабль вверх. В третьем и четвертом кадрах отображены боковые ускорители. На рис. 16.7 показан кадр "left". Обратите внимание, что слово "left" означает, что корабль будет двигаться влево, а пламя ускорителя находится справа. Кадр "explode" представляет собой начало небольшой анимации, в которой луноход взрывается. Эта анимация используется в том случае, когда игрок посадил корабль не на площадку.
В дополнение к клипу "background", который совсем не используется в коде, три других клипа представляют собой рельеф поверхности для трех уровней игры. Эти клипы называются "Ground - level I", "Ground - level 2" и "Ground - level 3".
Клип "pad" - всего лишь желтый прямоугольник, который показывает, что непосредственно под луноходом находится посадочная площадка.
Основная временная шкала этого ролика действительно сложная. Информация о кадрах и их содержимом приведена в табл. 16.1.
Таблица 16.1 Кадры основной временной шкалы
У вас также будет два простых клипа: "fuel gauge" и "fuel meter". Первый представляет собой пустой прямоугольник, а второй - сплошной. Клип "meter" помещается внутри клипа "gauge". Далее в коде вы укажете,чтобы при сжигании горючего размеры клипа "meter" уменьшались, то есть он будет занимать меньше места в прямоугольнике "gauge".
Платформенный скроллер
Исходный файл: Platform.fla
После первой волны аркадных игр, которая спала где-то в начале 80-х, следующим значительным течением было появление игр типа платформенный скроллер. Этот жанр приобрел ширенную популярность после появления серии игр "Mario Bros" от компании Nintendo. В конце 80-х платформенные скроллеры были абсолютным фаворитом среди консольных игр. Игры этого типа продолжают выходить и сегодня.
Игровой процесс типичного скроллера состоит в следующем: герой игры передвигается взад и вперед по двухмерному миру (вид сбоку). Игровое
пространство имеет несколько горизонтальных уровней - платформ, и игрок может прыгать и перемешаться по ним. Цель состоит в собирании различных предметов, за которые начисляются очки, и в том, чтобы избегать (а также уничтожать) других созданий игрового мира.
На рисунке 16.8 показан простенький пример скроллера с лисой в главной роли. Лиса может перемещаться туда-сюда по горизонтали и прыгать по платформам. При этом ей необходимо собирать орехи и избегать кроликов.

Рисунок 16.8 Реализованный во Flash платформенный скроллер содержит все основные элементы этого жанра
Подготовка ролика
В этом ролике не так много библиотечных элементов. На переднем плане сверху и снизу расположены элементы (см. рис. 16.1), представляющие собой интерьер вашего корабля. Все элементы переднего плана, включая текстовые области подсчета очков и повреждений внизу экрана, находятся в клипе "foreground". Благодаря этому можно легко поместить весь клип на передний план относительно пуль и астероидов.
Объекты-астероиды расположены в клипе "rock", который состоит из трех частей. Первая часть - статический кадр с изображением астероида, когда он приближается к кораблю. Вторая часть состоит из нескольких кадров анимации: взрыв астероида при попадании в него пули. Эта последовательность помечена как "explode red". И последняя часть - последовательность "explode blue". Просмотрите исходный ролик на Web-сайте, чтобы понять, как был создан этот клип (рис. 16.2).
В ролике находится также клип "point", в котором генерируются объекты-пули, и клип "cursor", заменяющий обычный вид курсора на перекрестие.
В ролике на главной временной шкале расположены три кадра: "start", "play" и "game over". Все действие происходит в кадре "play".

Рисунок 16.2 Взрыв астероида (клип "rock")
Библиотека для этого ролика несложная. В ней содержатся астероиды трех типов: "rock1", "rock2" и "госк1". Для того чтобы внести в игру некоторое разнообразие, каждый раз при создании астероида случайным образом выбирается один из трех клипов.
В клипе "ship" первый кадр - статический, во втором кадре начинается анимация, которая показывает, как загораются ускорители. Первый кадр этой анимации называется "thrust". Вместо того чтобы расположить корабль на рабочем поле с помощью команды attachMovie, его помешают в центр поля вручную, поэтому можно не заботиться о создании и размещении этого клипа с помощью кода.
Для формирования пуль используется клип "bullet". Код игры содержится в клипе "actions" и сценарии кнопки "button". Единственная кнопка на экране, реально выполняющая функцию кнопки, - это кнопка Play.
В ролике будут находиться кадры "start", "play", "ship hit", "level over" и "game over", в каждом из которых создается соответствующий текст. В каждом кадре, кроме "play", находится копия кнопки Play, но к каждому экземпляру этой кнопки прикреплен разный код. Просмотрите ролик. Spacerocks.fla, чтобы понять, где расположены все эти элементы и какой код прикреплен к каждому из них.
В ролике Mazechase.fla всего лишь несколько библиотечных эталонов, основными из которых являются фон, лиса, кролик и ягода.
Создать фон просто, но делать это следует аккуратно. Представьте себе экран в виде сетки из квадратов со стороной 25 пикселов. Ягоды располагаются на всех пересечениях линий сетки, кроме тех, которые расположены на фоне, а не на дорожке лабиринта.
На рис. 16.5 представлен клип "background", для которого отображена сетка размером 25x25. Сетку можно изменить, выбрав пункт меню View -> Grid-> Edit Grid (Вид -> Сетка -> Редактировать).

Рисунок 16.5 Когда в программе Flash отображена сетка, можно увидеть пересечения линий, на которых появятся ягоды
Сетка помогает быстро создать фон с помощью инструмента рисования прямоугольников. Для этого нужно обвести контуром некоторые области сетки и залить их цветом. Вы должны быть уверены, что границы фона немного перекрывают линии сетки. Когда программа будет помешать ягоды на пересечения линий сетки, они не появятся вдоль границы фона.
Первый кадр клипа "fox" - обычный статический кадр, в остальных кадрах представлена небольшая анимация - лиса съедает ягоду. Когда это происходит, клип воспроизводит второй кадр: игрок видит, как лиса ест ягоду, а затем клип возвращается к первому кадру.
В клипе "berry" два кадра: первый содержит изображение ягоды, а второй пустой. Когда лиса съедает ягоду, клип переходит ко второму кадру. Таким образом, клипы остаются на рабочем поле, но они видны до тех пор, пока ягода не будет съедена.
Клип "bunny" представляет собой анимацию: кролик всегда двигается, так что нет необходимости создавать статический кадр.
Все клипы, кроме "background", не будут видны до тех пор, пока не начнется ролик и программа не создаст их с помощью команды attachMovie.
В ролике содержатся практически такие же кадры, что и в ролике игры "Space Rocks": "start", "play", "lose life", "level over" и "game over".
Ролик содержит всего четыре клипа. Клип "fox" содержит некоторое количество кадров. В первом кадре изображена неподвижная лиса, далее некоторое количество кадров изображают анимацию бегущей (в одном направлении) лисы, и последние кадры изображают лису в прыжке. Имя экземпляра этого клипа на рабочем столе также "fox"; для экземпляра выставлен масштаб 25%.
Клип "box" - это просто коричневый квадрат размером 50x50. Этот клип содержит один кадр.
Клип "acorn" начинается с кадра со статичным изображением ореха. В этом кадре находится команда stop О . Остальная часть клипа изображает постепенное появление числа "100". Эта анимация проигрывается, когда игрок берет орех и ему начисляются очки.
Клип "bunny" состоит из двух кадров изображающих кролика, шевелящего лапками. Эта анимация работает независимо от направления перемещения кролика.
Клипам "box", "acorn" и "bunny" необходимо присвоить имена в панели Linkage Properties, чтобы был возможен их экспорт.
В главной временной шкале находятся три кадра. Первый содержит инструкции и кнопку Play, последний содержит сообщение "Game Over". В среднем кадре "Play" находится лиса и фон, изображающий землю. Все остальные элементы будут созданы программно при запуске игры.
Подход
В игре есть два активных элемента - астероиды и пули. Астероиды появляются около центра экрана и движутся к точке в области, которая по размеру больше экрана. Если астероид вылетает за пределы экрана, считается, что он пролетел мимо корабля. Если конечная точка движения астероида находится в области экрана, то астероид может столкнуться с кораблем и повредить его. При движении астероид увеличивается в размере, создавая иллюзию трехмерного пространства.
Пули вылетают из нижнего правого и нижнего левого углов экрана, они летят к точке, обозначенной положением курсора в момент выстрела. Когда пули достигают своей цели, они разрушают астероид, если он находится в этой точке.
Разрушая астероид, вы не только набираете очки, но и предотвращаете столкновение астероида с кораблем. Поэтому надо концентрировать свое внимание на тех астероидах, которые летят непосредственно на корабль.
Пространство игры представляет собой массив небольших объектов. Эти объекты имеют свойство type, соответствующие клипу, который будет использоваться. Клип имеет свойства х и у, определяющие его местоположение. Вот, например, как может выглядеть такой объект {type: "box", х:100, у: 0}.
Игрок начинает в позиции (0, 0). Если он передвигается вправо, то его позиция по х увеличивается. Если блок находится в позиции 0 по х, а игрок - в позиции 100, это значит, что блок располагается на 100 пикселов правее игрока. Если же игрок смешается в позицию 10 по х, то блок будет находиться на 90 пикселов правее.
Лиса не перемешается по горизонтали, а всегда находится в центре экрана. Все объекты прорисовываются в соответствии с их расстоянием от лисы. Когда речь идет о передвижениях лисы, имеется в виду ее виртуальное перемещение по пространству игры, а не по экрану.
Определение областей, в которых возможно (невозможно) передвижение лисы, является важнейшей задачей этой игры. Если лиса упирается в блок, она должна остановить свое перемещение в этой позиции. Эта задача реализована посредством постоянного сравнения положения лисы с положениями всех блоков. Если блок находится к игроку ближе других блоков в этом направлении, тогда его координаты принимаются : за самую далекую точку в данном направлении, до которой возможно перемещение лисы. Например, если блок находится на расстоянии 200 пикселов вправо от лисы, значит, лиса не может быть перемешена далее чем на 200 пикселов вправо. Если же в процессе проверки всех остальных блоков обнаружен блок, находящийся на расстоянии 100 пикселов от лисы, то значение 100 принимается как максимальное для возможного перемещения лисы в данном направлении.
То же самое происходит и по вертикали. Когда лиса прыгает, ей передается значение скорости по вертикали. При каждом обращении к кадру эта скорость регулируется за счет воздействия силы тяжести, так что лиса постепенно замедляется, а затем падает обратно вниз. Все объекты игрового пространства проверяются для определения наивысшей и наинизшей точек возможного движения лисы. Когда лиса достигает низшей точки, вертикальное движение прекращается. Это может быть самый низкий уровень ("земля") или одна из платформ других уровней.
Погоня в лабиринте
Исходный файл: Mazechasе.fla
Следующая игра - "Погоня в лабиринте" - классическая аркадная игра. Самое известное воплощение этой игры - Рас-Man.
В игре, фрагмент которой изображен на рис. 16.4, лиса бегает в лабиринте, пытаясь съесть все ягоды. Там же бегает злой кролик. Лиса должна не столкнуться с кроликом, пока не соберет все ягоды.

Рисунок 16.4 Лиса пытается собрать все ягоды, в то время как кролик стремится ее догнать
Создание кода
Как и в игре "Космический бой", за пределами рабочего поля находятся клип "actions" и кнопка "button", к которым добавлены соответствующие сценарии. В клипе "actions" содержится одна функция, начинающая уровень, и несколько функций, которые при каждом обращении к кадру перемещают элементы на экране.
onClipEvent(load) {
// Устанавливаем все элементы игры.
_root.startLevel();}
onClipEvent(enterFrame) {
// Перемещаем корабль на один шаг.
_root.shipMove();
// Перемещаем все пули на один шаг.
_root.bulletsMove();
// Перемещаем астероиды на один шаг.
_root.rocksMove();
// Выясняем, произошло ли столкновение.
_root.checkHits(); }
К кнопке "button" прикреплен код, содержащий несколько обработчиков событий on, которые реагируют на нажатие различных клавиш и совершают соответствующие действия.
on (keyPress "") {
// Выстрел.
shipFire() ;}
on (keyPress "") {
// Поворот на 30° вправо.
shipTirn(30);}
on (keyPress "") {
// Поворот на 30° влево.
shipTirn(30) ;}
on (keyPress "") {
// Перемещаем корабль вперед.
shipThrust(); }
on (keyPress "") {
// Корабль останавливается.
shipBreak();}
Когда игрок щелкает по кнопке Play, чтобы начать игру, в кадре "start" можно установить несколько переменных: обнулить количество набранных очков, начать первый уровень игры и указать, что игрок имеет три жизни.
on (press) {
gameLevel = 1;
lives = 3;
score = 0;
gotoAndPlay("play");}
Все функции находятся в сценарии кадра "play" основной временной шкалы. Первая функция вызывается в начале игры, а также сразу после того, как у игрока уменьшилось количество жизней.
Экземпляру клипа "ship" на рабочем поле присвоено имя "ship". В дополнение к стандартным свойствам клипа, таким как _хи_у, вы добавите несколько новых. Например, свойства dx и dy будут отражать расстояние, на которое перемещается корабль по горизонтали и вертикали соответственно.
Функция startLevel создает массивы bullets и rocks, в которых хранится список клипов пуль и астероидов.
Переменная level, используемая командой attachMovie, определяет уровень клипа, а не уровень игры, для этого применяется переменная gameLevel.
Далее для начала уровня создаются большие астероиды. На первом уровне - два астероида, на втором - три и т.д.
Потом в функции shipFire используется переменная timeOfLastFire, чтобы игрок не мог слишком часто стрелять.
В первом кадре содержится копия кнопки Play (Начать игру). Сценарий этого кадра не только переводит ролик к кадру "play", но и устанавливает несколько переменных.
on (press) {
lives = 3;
score = 0;
gameLevel = 1;
gotoAndPlay("play"); }
В кадре "play" содержится клип "actions" с прикрепленным к нему сценарием. Этот сценарий инициализирует все элементы в начале игры, после того как лиса теряет жизнь и перед началом нового уровня. Он также вызывает функции move и moveBunny для продолжения игры.
onClipEvent(load) {
// Инициализируем исходные элементы _root.startLevel();}
onClipEvent(enterFrame) {
// Перемещаем лису.
_root.move();
// Перемещаем кролика.
_root.moveBunny(); }
Все функции этой игры можно найти в сценарии основной временной шкалы для кадра "play". Сначала идет функция startLevel.
Основная работа данной функции заключается в создании ягод, для этого просматриваются все 15 положений по вертикали и 21 положение по горизонтали и проверяется, не расположены ли они поверх клипа "background". Если нет, то на пересечении линий сетки помешаются клипы "berry", а в массив berries добавляются указатели на эти клипы.
Также эта функция создает экземпляры клипов "fox" и "bunny", создает и устанавливает несколько новых свойств для каждого клипа, в том числе и dest (новое положение).
Обратите внимание, что свойство dest для клипов "fox" и "bunny" представляет собой просто координату: (х:275, у.275}. Благодаря этому значительно упрощается обращение к данным величинам. Например, можно обратиться к новому горизонтальному положению клипа, записав fox.deet.x.
function startLevel() {
level = 0;
// Создаем ягоды,
berries = new Array();
// Ищем пересечения линий сетки,
for (y=l; у
for (x=l; х
// Выясняем, расположены ли пересечения поверх фона.
if (!(background.hitTest(x*25,y*25,true))) {
// Создаем и размещаем клип "berry".
attachMovie ("berry", "berry"+level, level);
В трех кадрах "level1", "level2" и "level3" у вас будут клипы "actions", которые вызывают необходимые для игры функции. В начале уровня вызывается только одна функция, а в течение игры постоянно - другая.
onClipEvent(load) {
_root.startLevel();
} onClipEvent(enterFrame) {
_root.moveShip(); }
Обе эти функции расположены в основной временной шкале первого кадра. Сценарий ролика начинается с функции startGame, которая вызывается, когда в первом кадре игрок щелкает по кнопке Play. Она устанавливает значение переменной gameLevel, отображаемое в текстовом поле в верхнем правом углу экрана. Затем с помощью функции startLevel начинается первый уровень.
function startGame() {
gameLevel = 1;
startLevel(); }
Функция startLevel выполняет множество задач. Сначала она переводит ролик к кадру в соответствии со значением переменной gameLevel, затем помешает корабль вверху экрана. Скорость корабля, которая определяется величинами dx и dy, обнуляется. Для увеличения скорости корабля и для того, чтобы он начал двигаться вниз, используется переменная gravity.
В массивах hitPoints и footPoints содержатся координаты некоторых точек относительно центра корабля. Для определения, коснулся ли корабль поверхности луны, используются элементы массива hitPoints. А оба элемента массива footPoints нужны, чтобы определить, находятся ли обе опоры лунохода на посадочной площадке.
В массиве pads хранятся имена трех клипов посадочных площадок. На одном уровне имеется всего лишь две посадочные площадки, но язык ActionScript этого не учитывает.
function startLevel() {
gotoAndStop("level"+gameLevel);
// Размещаем клип корабля.
ship._x = 275;
ship._x = 25;
// Корабль не движется.
ship.dx = 0;
ship.dy = 0;
// Инициализируем гравитацию.
gravity = .1;
// Инициализируем индикатор горючего.
fuel = 100;
showFuel();
// Определяем точки корабля, которые могут коснуться
// поверхности Луны.
hitPoints = new Array();
hitPoints.push({x:-9, у: 13});
За небольшими исключениями весь код этой игры находится в кадре "Play". Он начинается с вызова функции startGame. Она инициализирует набор констант таких как скорость лисы и кролика, устанавливает начальное положение лисы и вызывает функции createWorld и creatObjects, которые создают все элементы игрового пространства.
startGame();
stop();
function startGame() {
// Устанавливаем константы,
floor = 350;
foxSpeed = 10;
bunnySpeed = 2;
jumpPower = 60;
// Задаем параметры лисы.
foxPos = {x:0,y:0};
fallSpeed = 0;
falling = false;
fox.swapDepths(999);
// При каждом обращении к кадру вызываем moveFox.
_root.onEnterFrame = moveFox;
// Создаем элементы игры.
createWorldf);
createObjects() ;}
Функция creatWorld создает массив objects и заполняет его положением всех блоков, орехов и кроликов. Она также задает глобальную переменную worldEnd, которая определяет правую границу игрового пространства.
function createWorld() {
objects = new Array();
objects.push({type:"box", x:250, y:0});
objects.push({type:"box", x:300, y:0});
objects.push({type:"box", x:500, y:0});
objects.push({type:"box", x:550, y:0});
objects.push({type:"box", x:600, y:0});
objects.push({type:"box", x:650, y:0});
objects.push({type:"box", x:700, y:0});
objects.push({type:"box", x:550, y:50});
objects.push({type:"box", x:600, y:50});
objects.push({type:"box", x:650, y:50});
objects.push({type:"box", x:850, y:0});
objects.push({type:"box", x:900, y:0});
objects.push({type:"box", x:1050, y:100});
objects.push({type:"box", x:1100, y:100});
objects.push({type:"box", x:1150, y:100});
objects.push({type:"acorn", x:150, y:0});
objects.push({type:"acorn", x:275, y:200});
objects.push({type:"acorn", x:1100, y:250});
objects.push({type:"bunny", x:400, y:0});
objects.push({type:"bunny", x:1200, y:0});
В этой игре можно стрелять
В этой игре можно стрелять по летящим астероидам небольшими пулями, Если пули попадают по объекту, он взрывается, не причиняя вреда кораблю. Однако если астероид не будет сбит, он может столкнуться с кораблем игрока и повредить его.
В игре подсчитывается число разрушенных астероидов и число астероидов, ударившихся о корабль. Некоторые астероиды могут пролететь сверху, снизу, справа или слева от корабля, не причиняя никакого вреда. Игра заканчивается тогда, когда произойдет 20 столкновений.
В этой игре предусмотрены уровни и ограниченное число жизней. Корабль может столкнуться с астероидом три раза. Если игрок взрывает все астероиды, то он переходит на следующий уровень, где астероидов больше и где они движутся быстрее.
Игрок может повернуть корабль вправо или влево, включить ускорители и таким образом переместить корабль вперед, а также может стрелять по астероидам. После использования ускорителя корабль продолжает двигаться по инерции. Если игрок повернет корабль и включит ускорители, его скорость изменится из-за сообщенного ему импульса. Нажав клавишу со стрелкой "вниз", игрок в любой момент может остановить корабль.
Пули - это небольшие клипы, исходное положение которых совпадает с положением корабля; пули движутся туда, куда направлен нос корабля в момент выстрела. Количество пуль в игре не ограничено, но игрок может выстрелить снова только после того, как пройдет время, необходимое на перезарядку.
Изначально размер астероида составляет 100%, скорость и направление движения произвольные. Когда по нему первый раз попадает пуля, он распадается на два .астероида, размер каждого из которых - 50%, направление их движения также произвольно. Эти астероиды, в свою очередь, могут распасться на два более мелких, размер которых будет составлять 25% от исходного астероида. Если после этого в астероид попадает пуля, он взрывается. Когда все астероиды будут разрушены, игрок сможет перейти на следующий уровень. Однако если астероид столкнется с кораблем, уменьшится количество жизней.
Игра, приведенная в качестве примера, имеет самые важные отличительные черты игры-погони в лабиринте. Ягоды исчезают с экрана, если лиса проходит через место, где они находятся. Лиса может переместиться с одной стороны экрана на другую, войдя в туннель справа или слева. Если кролик догонит лису, то она теряет одну жизнь.
Платформенный скроллер может быть довольно глобальным проектом. Противников (в нашем случае кроликов) можно атаковать, например, напрыгивая на них, некоторые объекты могут давать игроку специальные возможности, такие как увеличение скорости или возможность поражать неприятеля, который неуязвим в остальных случаях. Мы же постараемся сделать максимально простую игру, сосредоточив усилия на воплощении основных особенностей жанра. Лиса будет иметь возможность перемещаться взад-вперед и прыгать. Платформы в виде блоков будут препятствовать перемещению игрока по горизонтали, так что ему придется запрыгивать на них и проделывать часть пути поверху.
Перемещение игрока в этой игре означает прокрутку всего игрового пространства, в то время как игрок на самом деле все время находится в центре экрана. Ощущение движения лисы возникает за счет того, что в игре движется все, кроме самой лисы.
Каждый орех добавляет игроку 100 очков. Лиса должна собирать орехи и избегать кроликов.
Дизайн игрового пространства очень легко усложнить. После того как мы закончим разбирать процесс создания этого ролика, вы можете сделать собственный вариант уровня игры.
Демонстрация списка лучших игроков
Исходный файл: Highscores.fla
На Web-сайте надо разместить две программы, с помощью которых и будет формироваться список лучших игроков. Первая программа представляет собой демонстрационный ролик, показывающий, как набранные очки заносятся в базу данных и как они затем из нее извлекаются.
Кадр такого ролика, Highscores.fla, изображен на рис. 17.5. Область слева внизу позволяет вам ввести новый результат, а в области справа отображается список лучших игроков.

Рисунок 17.5 Ролик, отображающий список лучших игроков, позволяет проверить правильность работы программ, написанных вами на языке Perl
Имена игроков и очки выровнены по левому краю (Рис 17.5). Я использовал моноширинный шрифт (Courier). Если использовать другие шрифты, например Ariel, то будет не так просто выровнять столбцы в рамках одного текстового поля.
Все программные коды в файле Highscores.fla привязаны к двум кнопкам (см. рис. 17.5).
Часть "Добавить результат" отображает имя игрока и набранные им очки в текстовых окнах, содержимое которых может изменяться. Когда вы запускаете эту программу, вы можете ввести имя и набранные очки, а затем щелкнуть по кнопке Submit Score (Добавить результат). Ниже приведен текст программы, закрепленной за этой кнопкой.
on (press) {
// Путь к файлу
submitscore.pl. url = "submitscore.pl";
// Определяем объект LoadVars.
myLoadVars = new LoadVars();
myLoadVars.name = name;
myLoadVars.score = score;
// Пересылаем данные.
returnedVars = new LoadVars();
myLoadVars.sendAndLoad(url,returnedVars,"GET" resultText = "Sending...");
// Задаем результат.
returnedVars.onLoad = function!) { resultText = "Done."}}
Вы уже использовали объект LoadVars в главе 12 для создания игр-викторин. Тогда вы не отсылали никаких данных серверу, вам требовался лишь текстовый файл. В этом примере вы вызываете программу, написанную на Perl, чтобы отсылать данные на сервер. Элемент GET В конце команды SendAndLoad сообщает Rash, что данные будут передаваться с помощью протокола GET. Это один из вариантов, второй - использование протокола POST. Названные протоколы соотносятся с двумя способами передачи данных из форм, которые используются HTML-страницами. Данные, которые мы передаем, - это два свойства объекта myLoadVars: name и score. Когда передача завершается, выполняется функция, определяемая методом onLoad. В нашем случае она выводит сообщение в текстовое поле resultText. К кнопке Get Scores (Обновить список) также прикреплена небольшая программа, но здесь не требуется пересылать значения каких-либо переменных:
on (press) {
// Указываем путь к программе getscores.pl.
url = "getscore.pl";
// Запрашиваем данные.
myLoadVars = new LoadVars();
myLoadVars.load(url);
highscoresText = "Getting High Scores...";
/ / Данные получены.
myLoadVars.onLoad = function() {
highscoresText = myLoadVars.highscoresText;
}
Текст, выдаваемый программой Getscores.pl на выходе, начинается с high-ScoresText=. За счет этого оставшаяся часть текста помешается в одноименную переменную. Функция onLoad получает это значение из объекта myLoadVars и помешает в текстовое поле с соответствующим именем. Как только заканчивается пересылка текста, он выводится на экран.
Добавление списка лучших игроков в игру
Исходный файл: Whackafoxwithscores.fla
Как пример еще одной игры с использованием списка лучших игроков приведем файл Whackafoxwithscores.fla. Это все та же игра "Поймай лису", которую мы рассматривали в главе 8, но здесь она содержит еще и список лучших игроков.
К этой игре достаточно легко добавить список лучших результатов, потому что она подразделяется на три части. Сцена "Начало игры" была изменена таким образом, что уже при загрузке игры выводится список лучших игроков. Поэтому к стандартной команде stop О в начале первого кадра этой сцены вам понадобится добавить те коды, которые будут отвечать за отображение списка лучших игроков:
// Указываем путь к программе getscores.pl.
url = "getscore.pl";
// Запрашиваем данные. loadVariables (url,this);
// Выводим на экран информацию о том, что по кнопке щелкнули.
highscoresText = "Getting High Scores...";
stop() ;
Текстовое поле под названием highscoresText добавляется посередине экрана (рис. 17.6).

Рисунок 17.6 Теперь при загрузке игры "Поймай лису" на экран выводится список лучших игроков
В конце игры, в сцене "Игра закончена", появляется клип с несколькими текстовыми полями и кнопкой Submit Score. При этом очки, набранные в игре, должна подсчитывать и выводить сама программа. Сама по себе игра управляется действиями, которые относятся к клипу "actions" сцены "Игра". Поэтому переменная score привязана именно к этому клипу, а не к основной временной шкале. После добавления к тексту программы строки _root.score = score в основной временной шкале также появляется переменная score, которой присваивается число набранных очков. Когда приходит очередь сцены "Игра Закончена", первый кадр помешает набранные очки в клип "Добавление результатов". Одновременно удаляется предыдущее значение переменной name этого клипа.
sendscores.name = "" ;
sendscores.score = score;
stop();
На рис. 17.7 показан кадр из сцены "Игра закончена". Здесь вы можете видеть, что клип "Добавление результатов" содержит набранные игроком очки, текстовое поле, куда игрок должен ввести свое имя, и кнопку Submit Score.
Игрок вводит свое имя в первое текстовое поле, в то время как другое поле уже содержит набранные им очки, и он не может изменить результат. После этого игрок может щелкнуть по кнопке Submit Score, которая запустит следующую программу:
on (press) {
// Указываем путь к программе submitscore.pl.
url = "submitscore.pl";
// Отправляем значения переменных:
// "score" - счет игры,
// "name" - имя игрока.
loadVariables(url,this,"GET");
// Меняем кадр, чтобы по кнопке Submit нельзя было
// щелкнуть дважды,
play();
}

Рисунок 17.7 Последний кадр обновленной игры "Поймай лису" дает игроку возможность записать результат своей игры
Набранные очки пересылаются серверу таким же образом, как и в демонстрационном файле Highscores.fla. Отличие заключается в добавлении команды play(), благодаря которой происходит смена кадра. Второй кадр аналогичен первому, за исключением того, что здесь отсутствует кнопка Submit Score. Это сделано для того, чтобы игрок не мог несколько раз щелкать по кнопке, вводя таким образом несколько результатов.
Другие типы экранов загрузки
Только что рассмотренные экраны загрузки - стандартные. Кроме них существует множество других вариантов. Самый простой: можно отображать только статический кадр с надписью "Loading, Please Wait..." (Идет загрузка, пожалуйста, подождите...). Когда загрузка будет завершена, ролик просто перейдет следующему кадру.
Этот вариант можно усложнить и поместить какую-либо повторяющуюся анимацию в кадр.
Еще более сложный вариант: каждый кадр будет отображать различные этапы загрузки. Например, будет собираться некая картинка: чем ближе загрузка будет подходить к концу, тем более целостным будет становиться изображение.
Возможно, для создания таких экранов загрузки функции getBytesTotal () и getBytesLoaded () не понадобятся. Вместо них можно воспользоваться функцией ifFrameLoaded (), чтобы узнать, загружены ли все графические объекты определенного кадра. Эта функция пригодится, если вы хотите, чтобы пользователь начал какую-то часть игры, но не смог продолжить до тех пор, пока необходимые кадры не будут готовы.
Но лучше сделать время загрузки полезным для игрока. Например, поместить в кадр руководство к игре. Вместо того чтобы просто сидеть и смотреть, как заполняется полоса загрузки, игрок сможет узнать полезную и необходимую для него информацию.
Использование альтернативных возможностей
Основная концепция оптимизации - существование нескольких путей выполнения одной и той же задачи. Для большинства случаев это действительно так. Например, если вы хотите переместить графический объект с одной стороны рабочего поля на другую, можно использовать анимацию движения (motion tween) или написать код на языке ActionScript.
Когда вы создаете что-либо в программе Flash, у вас есть две альтернативы. Первая - выполнение одной задачи разными способами. Например, результат перемещения графического объекта с помощью построения промежуточных изображений или ActionScript одинаков.
Другая альтернатива - изменение программы, чтобы результат был похож, но все-таки отличался. Например, если графический объект движется по экрану слишком медленно, можно его уменьшить, и теоретически скорость его перемещения возрастет.
Ключ к успеху оптимизации состоит в том, что вы должны четко представлять себе существующие альтернативы и тщательно взвесить их преимущества и недостатки. Для определения преимуществ можно воспользоваться техникой, которая называется "установление контрольных точек".
Как обойти защиту от копирования
Этот план зашиты от копирования не безупречен. Есть один простой способ, с помощью которого вор может обойти вашу защиту. Он может оставить игру на вашем сервере и создать свою собственную HTML-страницу, в которой параметр src тэгов OBJECT И EMBED указывает на swf-файл, расположенный на вашем сайте. Пользователь будет хранить у себя HTML, а вы - swf-файл. Свойство _url будет сообщать, что игра находится на вашем сайте, то есть зашита от копирования действовать не будет.
Однако это далеко не лучший способ кражи, потому что файл все равно остается под вашим контролем. Вы всегда можете его переименовать или переместить в другое место. Если вы обнаружили, что кто-то украл вашу программу подобным образом, вы можете "поиграть" с ним: переместить игру в другое место сайта, обновить свою HTML-страницу, чтобы путь к игре был верным, а затем заменить старый swf-файл файлом, в котором будет содержаться грозное сообщение для посетителей сайта вора.
Как работает список лучших игроков
Список победителей можно создать разными способами. Один из них -написать программу на основе языка Java с использованием XML Socket, с которой ваша Flash-игра могла бы поддерживать связь через объект XML. Другой вариант - разместить на связанной с сервером Web-странице вашу Flash-игру, которая посылает и получает количество очков с помощью языка сценариев на основе Java.
Наиболее простым способом вести учет очков будет использование языка Perl, ориентированного на работу в сети. Именно об этом и пойдет сейчас речь. Значит, вам придется познакомиться с языком Perl и работой CGI-сценариев.
Сценарии CGI (Common Gateway Interface - общий шлюзовой интерфейс) - это программы, которые выполняются на стороне сервера по запросу клиента. Язык Perl (Practical Extraction and Report Language) - это язык программирования, схожий с языком ActionScript, но предназначенный для использования на Web-серверах. Обычно программы, написанные на языке Perl, имеют расширение .pi или .cgi, а не .html, которое характерно для простой Web-страницы. Когда пользователь просматривает программу, написанную на языке Perl, то, в отличие от текста программы, сохраненной как HTML-страница, ее команды воспринимаются сервером как команды языка Perl. Если Perl-программа получает какой-либо результат, он отсылается обратно на Web-сервер или, как в данном случае, передается Flash-ролику.
Язык Perl достаточно сложен, и его рассмотрению стоит посвятить отдельную книгу (и не одну). В действительности о Perl написано гораздо больше книг, чем о Rash. Если вы хотите получить более подробную информацию о Perl, идите в ближайший книжный магазин и выбирайте подходящую книгу.
В данном примере для составления списка лучших игроков используются две программы на языке Perl. Первая - Submitscore.pl - отвечает за получение нового результата игры из ролика Flash. Вторая программа, Get-scores, pi, отбирает 10 лучших результатов и отсылает обратно во Flash-ролик. Каждой из этих программ необходимо иметь доступ к небольшой базе данных, где будут храниться заработанные игроками очки. CGI-программы обычно обращаются к базе данных, находящейся на сервере, например СУБЛ MySQL. Однако в нашем примере используется более простой вариант - обычный текстовый файл. Каждая строка этого текстового файла содержит отличный от других строк результат игры. Каждая запись включает: имя игрока, набранные им очки и время, когда данный результат был занесен в базу данных. Имя игрока и его очки заносятся в программу Submitscore.pl из Flash-ролика, а время программа вводит самостоятельно.
Программа Getscores.pl просматривает текстовый файл с результатами игры и выполняет две функции. Во-первых, она анализирует каждую
запись и переписывает текстовый файл, убирая результаты, слишком долго находящиеся в базе данных. Это позволяет периодически обновлять список лучших игроков. Во-вторых, программа Getscores.pl размещает десять лучших результатов по порядку и затем отправляет их обратно во Flash-ролик. Именно этот список демонстрируется игрокам.
Мне нравится идея исключать из базы данных устаревшие записи. Это не дает возможность одному или нескольким рекордам лидировать в списке лучших результатов на протяжении нескольких лет. Кроме того, подобный подход побуждает хороших игроков вновь и вновь возвращаться к игре, чтобы снова побороться за право называться победителем.
Определение версии Flash-плагина
Исходный файл: Version.fla
Язык ActionScript во Flash 4 и 5 отличался так сильно, что ролик со сложным сценарием, созданный во Flash 5, скорее всего вообще бы не работал при использовании плеера четвертой версии. Однако Flash 5 и Flash MX достаточно сходны для того, чтобы ролик с кодом, созданным в версии MX, мог достаточно часто работать во Flash 5-плеере.
Это создает интересную проблему. Довольно легко сделать игру во Flash MX, которая будет работать у многих людей с Flash 5-плеером до какого-то момента. Когда же попадется участок кода, требующий Flash MX-плеера, игра или перестанет работать, или начнет вести себя непредсказуемым образом. Как узнать версию плеера Необходимо убедиться, что у пользователей установлен плеер шестой версии, прежде чем он начнет игру. Сделать это можно с помощью функции getVersion().
Функция getVersion () возвращает строку вида MAC 6,0 21,0. Первое слово - это аббревиатура платформы, обычно MAC или WIN. Вторая часть - это версия Flash-плеера, в настоящий момент запущенная на пользовательской машине.
Каждая часть номера версии отделена запятыми. Это создает трудности при сравнении имеющейся версии с требуемой. Как вы, например, определите, MAC 6,0 21,0 больше или равно версии 6?
С помощью некоторых операций со строкой вы можете перевести значение, возвращаемое функцией getVersion () во что-нибудь более пригодное к использованию. Следующая функция разбивает строку, используя пробелы и запятые как разделители. Она создает переменную -объект, к которому вы можете легко обращаться.
function getVersionNumber() {
// Определяем позиции запятых и пробелов.
spacePos = getVersion().indexOf(" ");
firstComma = getVersion().indexOf(",");
secondComma = getVersion().indexOf(",",firstComma+1);
thirdComma = getVersion().indexOf(",",secondComma+1);
lastChar = getVersion().length;
// Создаем объект version.
version = new Object();
version.platform = getVersion().substring(0,spacePos);
version.n1 = getVersion().substring(spacePos+1,firstComma);
version.n2 = getVersion().substring(firstComma+1,secondComma);
version.n3 = getVersion().substring(secondComma+1,thirdComma);
version.n4 = getVersion().substring(thirdComma+1,lastChar);
return(version);
}
В результате работы getVersionNumber получится примерно следующее:
{platform: MAC, nl: 6, n2: 0, пЗ: 21, п4: 0}
Таким образом, если вы хотите получить главный номер версии Flash, просто используйте getVersionNumber () .n1.
Оптимизация в ActionScript
Исходный файл: Benchmark3.fla
Тесты с помощью установки контрольных точек позволяют также выяснить, влияет ли на скорость ролика выбор альтернативных алгоритмов. Техника такая же: измеряем время на выполнение задачи и сравниваем его с временем, затраченным на выполнение задания альтернативным способом. Допустим, вы заметили, что в коде используется следующее сравнение:
if (myVariable == true) {
Понятно, что то же самое можно записать проще:
if (myVariable) {
Иногда первую строчку легче понять, но почему второй вариант увеличивает скорость работы программы? Вы могли использовать сотни или тысячи подобных сравнений внутри циклов и т.д.
Дело в том, что одно сравнение может экономить всего лишь несколько миллисекунд, то есть при сравнении одного варианта с другим разница едва ли будет заметна. Так что необходимо сравнивать тысячи подобных условий.
Следующий фрагмент построен для сравнения типа "истина/ложь". Сначала создается массив из 5000 элементов вида false и true. Этот процесс при подсчете времени учитываться не будет. Время засекается после того, как массив был создан. Измеряем время на подсчет количества элементов, равных true. Для этого используется оператор = =. В конце сценарий выводит время, которое потребовалось для 5000 сравнений.
function benchMacrk1() {
// Создаем новый массив.
testArray = new Array;
// Заполняем массив значениями true или false,
temp = false;
for(I = 0; I< 5000 ; I + +) {
testArray.push(temp);
if (temp == false) {
temp = true;
} else if (temp == true)
temp = false; }}
// Определяем время начала проверки.
startTime = getTimer();
// Подсчитываем, сколько значений true находится в массиве.
count = 0;
for(1=0; I
if (testArray[I] == ture) {
count++;}}
// Определяем время, потребовавшееся для проведения проверки.
totalTime = getTimer() - startTime;
// Отображаем результаты.
trace("Benchmark Test: using ==")
trace(:Total Time: " + totalTime + “ms”);}
Сам по себе результат ничего не значит. Однако вы также создадите функцию benchmark2, в которой строчка if (testArray [I] == true) { будет заменена на if (testArray [I]) {. Это единственная разница между функциями. Следовательно, если скорость выполнения сценария изменится, это произойдет вследствие замены строчек.
В результате оказалось, что второй вариант быстрее. На моем компьютере функции benchmark1 понадобилось 978 миллисекунд, a benchmark2 -958. Использование оператора == замедляет процесс сравнения истинных и ложных значений. Посмотреть, как работает приведенный выше код, в файл Benchmark3.fla.
Такие тесты с помощью установки контрольных точек проводят все профессиональные программисты независимо от того, на каком языке они пишут. Если вы часто пользуетесь языком ActionScript, будет полезно определить, какие методы работают быстрее. После проведения подобных тестов можно обобщить полученную информацию, которая позволит оптимизировать ваши Flash-игры.
Программы на языке Perl
Исходные файлы: Submitscore.pl, Getscores.pl
Программы Submitscore.pl и Getscores.pl, написанны на Perl. Чтобы эти программы работали на вашем сервере, понадобится загрузить эти файлы и отладить их. Если вы прежде этим не занимались, проконсультируйтесь с администратором сети или Internet-провайдером. Учтите, что не все серверы могут выполнять программы, созданные с помощью CGI. Если вы пользуетесь услугами дешевого хостинга или ваш провайдер предоставляет бесплатное Web-пространство для своих пользователей, будьте готовы к тому, что CGI-программы не будут работать на вашем сервере.
Хотя этот раздел не называется "Руководство по программированию на Perl для начинающих", ниже приведены листинги программ Submitscore.pl и Getscores.pl с краткими пояснениями, как работает каждая из их частей. Если вы незнакомы с программами, использующими стандарт CGI, обратитесь за разъяснениями к людям, сведущим в этой области.
Комментарий в языке Perl начинаются с символа #. Программа Submit-score.pl начинается с комментария, который на самом деле используется Web-сервером для определения адреса программы, интерпретирующей сценарии Perl. Нижеприведенный путь широко распространен и должен работать на вашем сервере. Если возникнут какие-либо проблемы, свяжитесь с вашим Internet-провайдером.
#!/usr/bin/perl
Первая строка текста самой программы начинается с отправки результативных данных обратно во Flash-ролик. Именно за это отвечает выражение Content-type: text /html, за которым следуют две пустые строки. Первая строка любого файла, посылаемого с Web-сервера, сообщает
браузеру (в данном случае Flash-ролику) о типе передаваемых данных. В этом примере передаваемые данные - обычный текст.
# Устанавливаем метку для текстового документа, отсылаемого
# назад браузеру.
print "Content-type: text/html\n\n";
Затем данные из Flash-ролика передаются в программу, где для их временного хранения используется переменная $get_data:
# Получаем переданные данные.
$get_data = $ENV{'QUERY_STRING'};
Когда данные пересылаются через сеть, они обычно кодируются таким образом, чтобы не допустить их некорректную передачу. Буквы не кодируются в отличие от пробелов, которые передаются как знак "+", и небуквенно-цифровых символов, передающихся как символьные последовательности, например %ОА. Чтобы раскодировать данные, необходимо дополнить программу следующими строками:
# Преобразуем закодированные символы.
$get_data =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack ("С",hex($l))/eg; #get_data =~ tr/\+/ /;
Далее нужно получить текущее время, измеренное на Unix-сервере в секундах, прошедших с 01.01.1970. Эти данные вы будете использовать как то время, когда был получен результат. Лучше оперировать именно этим показателем, а не временем, которое показывает сам Flash-ролик: игроки могут находиться в разных часовых поясах, а у некоторых из них может быть неправильно установлено время на их компьютерах.
# Вносим в базу данных время, оказываемое сервером, в секундах. $server_time = time();
Следующий шаг - организация цикла, который берет последовательность символов, хранящуюся в переменной $get_data, и разделяет ее на части. Например, такая последовательность имеет вид: name=Gary&score=967. Она разделяется на два элемента: до и после символа &, а затем каждый из этих элементов подразделяется еще на два - на ключ и на значение, теперь уже благодаря символу =.
# Обрабатываем полученные данные и создаем массив.
@split_data = split("&",$get_data);
foreach $data_item (@split_data)
{
($key, $value) = split("=",$data_item)
$info{$key} = Svalue;
}
Текстовой базой данных, где хранятся лучшие результаты, служит файл Highscore.txt. Чтобы запустить этот файл, загрузите его и настройте таким образом, чтобы с помощью программ на языке Perl можно было вводить в него информацию. Для этого предназначены следующие кодовые строки:
# Определяем имя файла, который будет содержать базу данных.
$filename = "highscore.txt";
# Открываем базу данных.
open(OUTFILE, "»$filename") || exit;
После того как файл будет открыт, программа внесет в него единичные записи, содержащие набранные очки, имя игрока и время, например: 967&Gary&978887513.
# Вносим информацию в базу данных.
print OUTFILE "$info{'score'}&$info{'name'}&$server_time\n";
Программа Submitscore.pl заканчивает свою работу, закрывая текстовый файл и пересылая определенную информацию во Flash. В данном случае переменной resultText присваивается символьная строка ОК.
# Закрываем базу данных.
Close(OUTFILE);
# Подтверждаем ввод данных,
print "resultText=OK\n";
# Завершаем программу,
exit;
Программа Getscores.pl несколько сложнее, чем Submitscore.pl. В ее задачу входит просмотр базы данных, удаление устаревших записей и затем выдача списка десяти лучших результатов. Начало этой программы аналогично началу Submitscore.pl. Далее файл открывает базу данных и перебирает все ее записи с использованием переменной типа "массив" @score_text.
#!/usr/bin/perl
# Устанавливаем метку для текстового документа,
# получаемого на выходе.
print "Content-type: text/html\n\n";
# Указываем имя файла, содержащего базу данных.
$filename = "highscore.txt";
# Просматриваем записи базы данных,
open(DATABASE,$filename) || exit;
@score_text = ;
close(DATABASE);
Затем программа подсчитывает, какое время (в секундах на сервере) было ровно семь дней назад.
# Определяем время на сервере.
$server_time = time();
# Выясняем, как долго сохранять полученные результаты.
# (7 дней * 24 часа * 60 минут * 60 секунд)
$keep_time = 7*(24*60*60) ;
Теперь база данных открыта и готова для записи. Старый файл перезаписывается с учетом новых данных.
# Открываем базу данных для перезаписи.
open(DATABASE,">" . $filename) || exit;
Следующий цикл проверяет каждую запись и определяет, как давно она была внесена в базу данных. Если запись устарела, то она не переписывается в новый файл.
# Просматриваем каждую запись.
foreach $score_line (@score_text) {
# Получаем данные о набранных очках.
@score_item = split(/&/,$score_line);
# Определяем время занесения результата.
$score_time = $score_item[2];
# Если запись не устарела, переписываем ее в новый файл.
if ($score_time > ($server_time-$keep_time)) {
print DATABASE "$score_Iine";
# Закрываем базу данных. close(DATABASE);
Далее программа сортирует результаты игры. Так как в начале каждой строки базы данных содержатся набранные очки, именно по ним упорядочиваются записи, от лучшего результата игры к худшему.
# Упорядочиваем набранные очки.
@score_text = sort { $b $а } @score_text;
Следующий цикл отбирает первые десять результатов и выдает их как выходные данные. Каждый элемент строки специальным образом форматируется. Эта строка выглядит, например, следующим образом: "l.Gary 967". После номера строки ставится точка. Затем идет имя игрока: если оно содержит меньше 18 символов, оставшееся место заполняется пробелами. Далее выводятся набранные игроком очки - они выравниваются по правому краю, и если число цифр меньше девяти, то свободные места с левой стороны также заполняются пробелами.
# Определяем число результатов,
# которые программа отошлет как выходные данные.
$num_scores = 10;
$score_count = 1;
# Просматриваем первые записи и отправляем данные,
print "highScoresText=";
foreach $score_line (@score_text) {
# Прочитываем записанные данные и создаем массив.
@split_data = split("&",$score_line);
# Выводим номер строки с точкой после него.
printf("%2i. ", $score_count);
# Выводим имя игрока, выравниваем по левому краю, оставшиеся
# свободные места до 18 символов заполняем пробелами,
printf("%-18s ",$split_data[l]);
# Выводим набранные очки, выравниваем по правому краю,
# оставшееся слева место до девяти символов заполняем
# пробелами.
printf("%9i\n",$split_data[0]); $score_count++;
if ($score_count > $num_scores) { last; } }
# Выходим из программы,
exit;
Если вы прежде программировали только на Flash и никогда раньше не сталкивались с Perl, вам будет достаточно сложно писать программы на этом языке. Можете не беспокоиться по этому поводу, потому что обычно подобные проекты разрабатываются двумя программистами совместно: один из них владеет языком Flash, другой - Perl. Если возможно, постарайтесь с кем-нибудь объединиться.
Сложности применения списка лучших игроков
Многие считают, что игра только выигрывает от добавления списка лучших результатов. Однако применение этого списка может вызвать определенные затруднения, которые вы, скорее всего, не приняли во внимание.
Давая игрокам возможность вводить в качестве их имен любую информацию, вы тем самым бесплатно предоставляете им на своем Web-сайте пространство для деятельности. Конечно, большинство игроков введут
свое имя или прозвище, но найдутся и те, которые воспользуются случаем написать что-нибудь нехорошее.
Почему бы не проверять Flash-игру или Perl-программу на наличие нецензурных выражений? Вы можете так и поступить, но это не решит проблему окончательно. Одни из игроков могут слегка изменить написание слов либо использовать между ними пробелы или тире, другие абсолютно нормальными словами скажут что-нибудь неприличное. Иначе говоря, совсем избежать неприятных ситуаций, скорее всего, не удастся.
Большие, профессионально сделанные сайты обычно требуют, чтобы перед тем, как сохранить результаты своей игры, пользователь зарегистрировался. Однако система учета очков зарегистрированных игроков гораздо сложнее примеров, которые описываются в этой главе. Для ее внедрения потребуется готовая система баз данных со встроенной системой зашиты.
Другая проблема - это жульничество. Как только будут объявлены лучшие результаты, игроки станут искать способы смошенничать. И это достаточно легко сделать. Можно использовать различные методы - от остановки игры в решающий момент, чтобы перевести дух и найти решение в сложившейся ситуации до использования "взламывающих" программ, которые могут считывать информацию из памяти компьютера игрока и записывать новые данные. Таким образом, 42 балла можно легко превратить в 42 миллиона баллов. Однако, если эти сложности вас не пугают и вы все-таки решили включить в игру список лучших игроков, не ограничивайте свои возможности только описанными здесь приемами. Попробуйте использовать другие языки программирования. Например, РНР - очень популярный язык, схожий с языком Perl. С равным успехом CGI-программы можно создавать на основе более старых и известных языков, таких как С и C++.
Сложные экраны загрузки
Исходный файл: Loader2.fla
На рис. 17.3 видно, что в текстовом поле отображается величина 63%. Вместо такого метода измерения можно сообщать пользователю, сколько байт уже загружено и каков размер всего ролика. Для этого нужно изменить значение loadingmessage, записав следующее:
_root.loadingmessage = int(bytesLoaded/1000) + "kb/" + int(totalFileSize/1000) + "kb";
Тогда вместо 63% вы увидите 90 Kb/143 Kb, что лично мне больше нравится.
Выполняя несложные математические вычисления, вы можете сообщить пользователю, как быстро идет загрузка. Для этого нужно создать переменные, в которых будет храниться количество загруженных байт и время на их загрузку. Теперь вы можете определить скорость загрузки, разделив первую величину на вторую. Это позволит спрогнозировать, сколько времени займет загрузка всего ролика.
Следующий код представлен в ролике Loader2.fla. Он похож на предыдущий фрагмент кода, только здесь на экран выводится еще и дополнительная информация: скорость загрузки и оставшееся время.
onClipEvent(load) {
// Получаем исходную информацию.
totalFileSize = _root.getBytesTotal();
startTime = getTimer О;
startBytes = _root.getBytesLoadedf);
// Прячем полосу загрузки,
this. _xscale = 0;}
onClipEvent(enterFrame) {
// Выясняем, сколько байт уже загружено.
bytesLoaded = _root.getBytesLoaded();
// Преобразуем это значение в величину от 0 до 1.
amountLoaded = bytesLoaded/totalFileSize;
// Преобразуем полученное значение в величину от 0 до 100.
percentLoaded = int(100*amountLoaded);
// Определяем масштаб полосы загрузки.
this._xscale = percentLoaded;
// Определяем скорость загрузки.
timeSoFar = getTimerО - startTime;
speed = bytesLoaded/timeSoFar;
// Выясняем, сколько времени осталось до конца загрузки.
bytesLeft = totalFileSize - bytesLoaded; timeLeft = (bytesLeft/speed)/1000;
// 'Преобразуем полученное значение
// в величину с одной цифрой после запятой.
speed = int(10*speed)/10;
// Устанавливаем текстовые поля.
_root.bytesMessage = int(bytesLoaded/1000) + "kb/" + int(totalFileSize/1000) + "kb";
_root.speedMessage = speed + "k/sec";
_root.timeMessage = int(timeLeft) + " seconds remaining";
Поскольку мы округлили значение timeLeft до целого числа, то в течение последней секунды загрузки в соответствующем окне будет отображаться ноль. Если вас не устраивает такое положение дел, то вы можете округлить это значение до одного или большего количества знаков после запятой.
// Проверяем, все ли уже загружено.
if (amountLoaded >= 1.0) {
_root.gotoAndStop("complete");
}}
Список лучших игроков
В большинство Flash-игр играют через Internet. Это значительно увеличивает число желающих сыграть. Самый простой способ воспользоваться преимуществами коллективной игры - это включить в игру список лучших игроков. Сервер будет вести счет очков, набранных участвующими в игре людьми, а они, в свою очередь, смогут увидеть лучшие результаты.
Однако добавить к игре список лучших игроков - не простая задача. Навыков только Flash-программирования будет недостаточно, потому что подобная программа должна быть написана таким образом, чтобы Internet-сервер смог получить, обработать и упорядочить заработанные очки.
Требуемые версии
Обычно вам нужно сравнить номер версии с минимальными требованиями, необходимыми для игры. Например, вы можете задать минимальную версию, необходимую пользователю для вашей игры, 6.0.21.0. Вот функция, которая берет полный номер требуемой версии и сравнивает с номером версии, запушенной в настоящее время на компьютере пользователя. Она возвращает истинное значение только в том случае, если установленная версия больше или равна требуемой.
function requiredVersion(required) {
version = getVersionNumber();
// Возвращаем false, если номер версии меньше необходимого,
if (version.nl < required.nl) return(false);
// Возвращаем true, если номер версии больше необходимого,
if (version.nl > required.nl) return(true);
// Главные позиции номера совпадают, сравниваем следующие
// позиции.
if (version.n2 < required.n2) return (false);
if (version.n2 > required.n2) return (true);
if (version.n3 < required.n3) return (false);
if (version.n3 > required.n3) return (true);
if (version.n4 < required.n4) return (false);
if (version.n4 >= required.n4) return (true);
Вы можете использовать эту функцию так:
if (requiredVersion) ({nl: 6, n2: 0, пЗ: 21, п4:0})}
gotoAndPlay("start");
} else {
gotoAndStopt"version problem");}
ЕСЛИ версия пользователя меньше, чем 6.0.21.0, ролик переходит к кадру, который объясняет, что данная игра требует обновления версии плеера.
Все коды в функциях getVereionNumber и requiredVersion будут работать и с Flash бис Rash 6. Весь код ничего не будет стоить, если будет работать только с Flash 6. Идея состоит в том, чтобы предупредить пользователя Flash 5-плеера о возможных проблемах.
Обычное данную функцию предполагается использовать для того, чтобы обнаруживать небольшие обновления Flash-плеера. Предположим, например, что Macromedia выпускает Flash версии 6.0.42.0. Эта версия содержит исправление, которое необходимо для корректной работы вашей игры. Вы должны проверить, есть ли у пользователя данная версия, и предупредить его, если ее нет.
Важно, чтобы эта проверка возвращала true только в том случае, если у пользователя установлена требуемая версия или более новая. Обычная ошибка, которую делает программист, это поиск точного номера версии, например, 6. Тогда, если у пользователя установлена 5-я или любая другая версия, он получает предупреждение о необходимости обновления. Спустя год выходит версия 7, а поскольку версия 7 также не является версией 6, пользователь получает точно такое же предупреждение! Я постоянно сталкиваюсь с этим в программировании во Flash, Stockwave и JavaScript. Функция requiredVersion всегда возвращает true если версия пользователя более новая, чем требуемая.
Установление контрольных точек
Исходный файл: Benchmarkl.fla
Если вы хотите сравнить два альтернативных варианта увеличения скорости, вам нужно как-то ее измерить. Конечно, вы можете определить скорость на глаз: когда объект движется быстрее; но такой способ не очень точен. Установление контрольных точек позволяет выяснить, какая из альтернатив работает быстрее и насколько.
Обычно с помощью контрольных точек сравниваются две или более альтернатив при выполнении одинаковых или аналогичных задач. В каждом случае засекается время в начале и конце выполнения задания.
В результате вы определяете, сколько времени необходимо на выполнение этого задания. Проведя несложные математические расчеты, вы можете преобразовать эту величину в скорость воспроизведения ролика, то есть количество кадров в секунду (fps - frames per second).
В качестве примера возьмите какой-либо графический объект, перемещающийся через рабочее поле. На рис. 17.1 в центре экрана изображена лиса в тот момент, когда бежит справа налево.

Рисунок 17.1 В течение 30 кадров большая лиса бежит справа налево
Индикатор в правом верхнем углу рис. 17.1 показывает, что скорость этого ролика составляет 35 кадров в секунду. На самом деле ролику задана скорость 120 кадров в секунду. 35 кадр/сек - реальный результат работы Flash-проигрывателя, который воспроизводит анимацию.
Для того чтобы в верхнем правом углу отображалась надпись "35 fps", необходимо добавить небольшой фрагмент кода. В первый кадр кода надо поместить следующую строчку, чтобы запомнить время начала анимации:
startTime = getTimer();
В последнем, 30-м кадре, программа, используя время начала и конца анимации, подсчитывает, сколько миллисекунд заняло ее воспроизведение. Полученная величина отображается в текстовом поле.
totalTime = getTimerO - startTime;
totalFrames = 30;
fps = totalFrames/(totalTime/1000);
readout = int(fps) + "fps";
Результат работы этого кода можно увидеть в ролике Benchmarkl.fla. Когда я проигрывал ролик на своем Макинтоше в окне предварительного просмотра, результат варьировал от 33 до 35 кадр/сек. Скорость также зависит от изменения масштаба. Попробуйте изменить масштаб в окне предварительного просмотра и посмотрите, как изменится скорость ролика.
Важно помнить, что максимальная скорость, которую может предоставить Flash в таких случаях, - 120 кадр/сек. Если вы укажете скорость по умолчанию, равную, скажем, 12 кадр/сек, анимация будет проигрываться только с этой скоростью или медленнее. Даже если один способ будет быстрее другого, вы не заметите никакой разницы, так как в обоих случаях скорость окажется равна 12 кадр/сек.
Рисунок 17.1 был получен при проигрывании ролика в окне предварительного просмотра. Что же произойдет, если открыть окончательный swf-файл с помощью Flash-проигрывателя вне программы Flash? Вы получите несколько лучший результат, примерно 42 кадр/сек. То есть ролик воспроизводится Flash-проигрывателем быстрее, чем в окошке предварительного просмотра. Проигрывание Flash-ролика в браузере (Internet Explorer 5.1) дает меньшую скорость - примерно 22 кадр/сек.
Все числа и параметры скорости работы относятся к компьютеру, на котором работал автор. У вас, естественно, могут быть совсем другие значения.
Конечно, эти числа имеют значение только при сравнении друг с другом. Когда те же действия производились на других компьютерах (как под управлением ОС Windows, так и Macintosh), результаты были другими: где-то ролик проигрывался быстрее, где-то - медленнее. Вы даже не можете быть уверены, что скорость анимации будет одинаковой на другом компьютере того же производителя и такой же модели. У компьютера может быть другое разрешение, на нем могут больше работать в сети (это уменьшит скорость воспроизведения ролика при загрузке из сети), или диск может быть больше фрагментирован. Проводить тест установления контрольных точек имеет смысл только на одинаковых компьютерах при одинаковых условиях.
Возможности Flash 6-плеера
Кроме выяснения номера версии Flash-плеера, вам также может понадобиться узнать другие возможности пользовательского варианта плеера. Флэш может работать на разных платформах, например, на карманных компьютерах. Некоторые из этих устройств неспособны поддерживать весь набор свойств, которыми оперирует Flash 6 на MAC и Windows.
Вы можете проверить некоторые характеристики системы с помощью объекта System.capabilities. Свойства этого объекта содержат требуемые параметры. Вот пример кода, который совершает цикл по всем свойствам и возвращает каждое значение.
// Список всех свойств.
capabilitiesDisplay = "";
for(i in System.capabilities) capabilitiesDisplay += i"+: "+System.capabilities[i] + newline;}
Возвращаемый список выглядит примерно так на моем Macintosh Powerbook:
language: en-US
input: point
manufacturer: Macromedia Macintosh
os: Mac OS 10.1.3
serverString:
A=t&MP3=t&AE=t&VE=t&ACC=f&DEB=t&V=MAC%206%2C0%2C21%2C0&M=Macromedia
Macintosh&R=1152x768&DP=72&COL=color&AR=l&I=point&OS=Mac OS
10.1.3&L=en
isDebugger: true
version: MAC 6,0,21,0
hasAudio: true
hasMP3: true
hasAudioEncoder:true
hasVideoEncoder: true
screenResolutionX: 1152
screenResolutionY:768
screenDPI: 72
screenColor: color
Одна из проблем, связанных с использованием System.capabilities,состоит в том, что нет никакой гарантии, что названия свойств и типы значений остаются постоянными от плеера к плееру. Вам придется проверить System.capabilities на любой системе, на которой хотите проигрывать ваш клип. Потом вам нужно составить лист возможных свойств и значений, которые хотите проверить. Например, вы можете заметить,что на некоторых плеерах hаsМРЗ не работает, а некоторые плееры даже не показывают свойство hаsМРЗ. Поскольку Flash 6-плеер может быть подсоединен к разным машинам, только время покажет, насколько различным может быть список System, capabilities работает.
Одно из полезных применений System.capabilities состоит в том, что можно взять значения свойств screenResolutionX и screenResolutionY, чтобы, например, сообщить пользователю, что установки его монитора соответствуют размеру экрана, который слишком мал для удобного просмотра вашего ролика. Вы также можете разбить на части свойство System, capabilities, os, также, как мы уже разбирали get .Version О , чтобы можно было проверить, обладает ли пользователь достаточно новой версией операционной системы.
Выбор лучшей альтернативы
Исходный файл: Benchmark2.fla
Обратившись к предыдущему ролику, приведенному в качестве примера, предположим, что скорость в 22-42 кадр/сек для вас недостаточна. Допустим, в анимации лиса должна быстро промелькнуть, пробежать с одной стороны экрана на другую. При 22 или даже 42 кадр/сек вы не получите требуемого результата.
Можно уменьшить число кадров с 30 до 15, скорость увеличится в два раза, но анимация станет менее плавной. Так как клип лисы управляет длиной шага, лиса сделает в два раза меньше шагов, чтобы пробежать то же самое расстояние.
Если такой вариант не помогает, возможно, стоит изменить размер лисы. Что произойдет, если уменьшить лису в два раза? С одной стороны, число векторов изображения останется прежним, то есть время на построение изображения не зависит от его масштаба. С другой стороны, так как лиса будет меньше, для создания ее изображения понадобится меньшее число пикселов, следовательно, скорость ролика увеличится (понадобится меньше ресурсов для отображения каждого кадра).
Проверить эти гипотезы можно с помощью установки контрольных точек. Если уменьшить в два раза фигуру лисы в ключевых кадрах, вы получите такую же анимацию, только лиса будет меньше. Сценарий покажет, повлияло ли это на скорость ролика.. Результат сравнения показан на рис. 17.2.

Рисунок 17.2 Ролик с небольшим изображением проигрывается быстрее
Маленькая лиса двигается быстрее, чем большая. Во Flash-проигрывателе на моем компьютере ролик воспроизводился со скоростью 60-70 кадр/сек, что примерно в два раза превышает скорость предыдущего ролика. Это подтверждает теорию о том, что для построения меньшего графического объекта требуется меньше времени.
Теперь остается выяснить, удовлетворяет вашим потребностям анимация с меньшим изображением лисы? Если да, то вопрос выбора альтернативы решен.
Выполнение и оптимизация
При разработке игр с помощью программы Flash всегда возникает вопрос о скорости. До пятой версии Rash язык программирования был недостаточно эффективным и не позволял создавать многие игры. Но даже версия 5 была довольно медленной. Достаточно медленной, чтобы было невозможно реализовывать многие игры. Версия MX значительно улучшила быстродействие программы. Теперь можно создавать игры, для которых Flash 5 был слишком медленной программой. Даже игры, созданные в пятой версии и запушенные с помощью проигрывателя версии 6, смотрятся лучше. Но независимо от того, используете ли вы версию 5 или MX, техника оптимизации может помочь ускорить любую игру или программу.
Защита от копирования
Исходный файл: Copyprotection.fla
Итак, как помешать кому-либо украсть вашу игру? Никак. Но вы можете помешать ему проигрывать игру с другого сайта, таким образом, украденная игра станет бесполезной.
Ключ к такой защите - свойство _url, которое возвращает строчку, содержащую весь путь к вашему swf-файлу. Если ролик располагается по адресу http://www.ktrnk.org/my .swf. именно эту строчку вернет свойство _url.
После того как вы ее получили, можете разбить ее на части и выделить имя основного домена. Например, в вышеприведенном адресе основной домен – ktrnk.org. Просмотрите следующий фрагмент программы Copyprotection l.fla:
// Показываем весь путь.
urlText = "This game is being loaded from: " + _url;
// Получаем строку, находящуюся между символами "://"
//и следующим символом "/". cl = _url.indexOf("://"+3; с2 = _url.indexOf("/", cl);
domain = _url.sunstring(cl, c2);
// Удаляем все символы перед первой точкой.
сЗ = domain.lasrIndexOf(".")-1;
с4 = domain.lastlndexOf(".", сЗ) +1;
domain = domain.substring(c4, domain.length);
// Отображаем основной домен.
domainText = "The root domain is: " + domain;
Полученное имя основного домена вы можете сравнить с доменом, на котором находится ваш сайт. Основной домен, используемый в пути к вашей игре, для разных пользователей может выглядеть по-разному. Например, адреса http:// ktrnk.org и http://www. ktrnk.org относятся к одной страничке, но свойство _url для них будет различным. Также в адресах некоторых сайтов перед доменом могут бьпъ указаны не только символы типа "www.", например, www .games. ktrnk.org.
Если основной домен не соответствует тому, который ожидает программа, значит, игру украли. В этом случае вместо перехода к ролику игры программа может перейти к другому кадру, в котором, например, будет выводиться угрожающее сообщение.
Возможно, вы не захотите, чтобы сообщение было слишком угрожающим. Много раз я предоставлял клиенту лицензированную копию одной из игр для его сайта и забывал изменить код, чтобы игра шла на его сайте. Если вы попадете в такую ситуацию, мнение клиента о вас может измениться в худшую сторону.
Исходный файл: Copyprotection2.fla
Далее следует фрагмент программы, сравнивающей свойство _url с тем доменом, на котором располагается ваша игра. Этот код вы можете посмотреть в файле Copyprotection2.fla.
// Получаем строку, находящуюся между символами "://"
//и следующим символом "/".
cl = __url.indexOf("://"+3; с2 = _url.indexOf("/", cl) ;
domain = _url.sunstring(cl, c2);
// Удаляем все символы перед первой точкой.
сЗ = domain.lasrIndexOf(".")-1;
с4 = domain.lastlndexOf(".", сЗ) +1;
domain = domain.substring(c4, domain.length);
// Переходим к соответствующей странице,
if (domain != " ktrnk.org ") {
gotoAndPlay("stolen");
} else {
gotoAndPlat("start");
Вместо того чтобы ролик переходил к другому кадру, вы можете сделать так, чтобы он вызывал функцию getURL () с адресом HTML-страницы, на которой и будет находиться ваше гневное сообщение. Таким образом, не нужно будет помещать кадр с сообщением в каждый ролик, который вы создаете.
Сайт: Аннимация - Видео - Графика
- Анимация на сайте
- Графика на сайте
- Фотография на сайте
- Кино на сайте
- Flash на сайте
- Видео для сайта
- Premiere Pro
- Vstudio
- VirtualDub
- Sonic Scenarist
- DVD
- Изображения для сайта
- Пакет Photoshop
- Adobe Illustrator
- Adobe Illustrator
- CorelDRAW
- CorelXARA
- Maya