Руководство по actionscript. часть 7, стр. 024
2. В папке megabridaldepot создайте новый текстовый файл MegaBridalDepot. as.
3. В файле введите следующий код (дополнительные сведения о методиках загрузки, применяемых в следующем коде, можно найти в подразд. «Использование библиотеки классов в формате SWF в приложении Flex Builder 2»):
package { import flash. display.*; import flash. net.*; import flash. system.*; import flash. events.*;
i mport com. beavercore. effects. TextAni mati on;
public class MegaBridalDepot extends Sprite { public function MegaBridalDepot ( ) { var libLoader:Loader = new Loader( ); 1i bLoader. contentLoaderlnfo. addEventLi stener(
Event. INIT, initListener);
libLoader. load(
new URLRequest(«beavercore. swf»),
new LoaderContext(false, ApplicationDomain. currentDomain));
}
private function initListener (e:Event):void { var textAni:TextAnimation = new TextAnimation( ); textAni. start( );
}
}
}
4. В среде разработки Flash создайте новый FLA-файл и сохраните его в папке megabridaldepot под именем megabridaldepot. Да.
Руководство по actionscript. часть 7, стр. 025
5. В поле Document class (Класс документа) палитры Properties (Свойства) (команда меню Window > Properties (Окно > Свойства)) введите MegaBridalDepot.
6. Скопируйте файл beavercore. swc в папку megabridaldepot.
7. Теперь скопируйте файл beavercore. swf в папку megabridaldepot.
8. Выберите команду меню Control > Test Movie (Управление > Проверка фильма).
На шаге 6 описанной процедуры файл beavercore. swc включается в путь к классам проекта megabridaldepot. fla, обеспечивая доступность классов и определений из библиотеки beavercore. swc для проверки типов на этапе компиляции. Стоит отметить, однако, что классы и определения из SWC-файла применяются только для проверки типов и не включаются в экспортируемый файл megabridaldepot. swf. Чтобы включить определения из SWC-файла в экспортируемый SWF-файл, добавьте SWC-файл в библиотеку исходного FLA-файла, как было описано ранее, в подразд. «Использование библиотеки классов в формате SWC в среде разработки Flash» предыдущего раздела.
Ш«_ J Включение SWC-файла в путь к классам FLA-файла обеспечивает доступность опре-I делений из этого SWC-файла для проверки типов на этапе компиляции, но не добав-— ляет эти определения в SWF-файл, экспортируемый из данного FLA-файла. Результат эквивалентен включению SWC-файла в пути внешних библиотек при компиляции проекта с помощью приложения Flex Builder 2 или компилятора mxmlc. Разработчики на языке ActionScript 2.0 должны отметить, что в файле _exclude. xml больше нет необходимости; механизм использования файла _exclude. xml в приложении Flash CS3 не поддерживается.
В результате выполнения предыдущих шагов компилятор сгенерирует SWF-файл MegaBridalDepot. swf и выполнит его в режиме Test Movie (Проверка фильма). Файл не включает класс TextAnimation. Вместо этого данный класс загружается на этапе выполнения. Как только класс будет загружен, в окне Output (Вывод) появятся следующие сообщения:
Imagine a text effect with great majesty. Effect now starting.
Руководство по actionscript. часть 7, стр. 026
На этом наша благородная миссия по распространению кода завершена. И, между прочим, подошла к концу и книга…
Неужели на этом все закончится?
На протяжении 31 главы мы рассмотрели множество различных инструментов и методик программирования, и теперь настал ваш черед экспериментировать с ними. Возьмите то, что было изучено, и реализуйте свои собственные идеи и проекты. Не жалейте, если вы потратили большую часть своего времени на изучение языка ActionScript, и не думайте, что эти знания не пригодятся вам в будущем. Большинство концепций, представленных в этой книге, можно найти во многих других языках. Приобретенные знания по ActionScript помогут вам в таких языках, как, например, Java, С++, Perl и Visual Basic.
Программирование — это вид искусства. По существу, оно включает в себя все крушения надежд и энтузиазм, присущие скульптуре, прозе, рисованию или музыке. И оно подчиняется основному закону творчества: нет предела совершенству. Каждый день занимаясь программированием, вы создаете что-то новое и продол-
жаете обучаться. Этот процесс никогда не прекращается. Хотя эта книга подошла к концу, ваше путешествие в мир программирования будет продолжаться до тех пор, пока вы разрабатываете код.
Если попутно вы увидите или сделаете что-то интересное, отправьте мне сообщение на адрес colin@moock. org.
Благодарю вас за то, что вы разделили со мной часть вашего путешествия в мир программирования. В добрый путь!
ПРИЛОЖЕНИЕ
Окончательная версия программы «Зоопарк»
В этом приложении представлена окончательная версия кода программы Зоопарк», которая рассматривалась в части I. Для добавления графики и интерактивности в программу применяются методики, рассмотренные в части II.
Руководство по actionscript. часть 7, стр. 027
I Код для программы «Зоопарк» можно загрузить по адресу http://www. moock. org/eas3/
*v 4 т examples.
Обратите внимание, что код в этой версии виртуального зоопарка подвергся структурным изменениям, отражающим реальные шаблоны проектирования. В частности, добавлены два новых класса: FoodButton, представляющий простую интерактивную кнопку-текст, и Virtual Pet View, обеспечивающий графическое представление экземпляров класса VirtualPet.
Класс VirtualZoo претерпел следующие значительные изменения:
? теперь он создает экземпляр класса VirtualPetView, используемый для отображения животного на экране;
? он ожидает, пока экземпляр класса VirtualPetView загрузит необходимые изображения, прежде чем приступить к имитации животного.
Класс VirtualPet претерпел следующие значительные изменения:
? константы VirtualPet. PETSTATE_FULL, VirtualPet. PETSTATE_HUNGRY, VirtualPet. PETSTATE_STARVING и VirtualPet. PETSTATE_DEAD представляют физическое состояние животного;
? переменная экземпляра petstate хранит текущее физическое состояние животного;
? приемники событий уведомляются об изменениях в физическом состоянии животного посредством события VirtualPet. STATE CHANGE;
? приемники событий уведомляются об изменениях в имени животного посредством события VirtualPet. NAME_CHANGE;
? чтобы изменить количество калорий в желудке животного, класс VirtualPet использует метод setCalories ( ); при необходимости метод setCalories ( ) изменяет состояние животного с помощью метода setPetState ( );
? физическое состояние животного изменяется методом setPetState ( ), который генерирует соответствующее событие VirtualPet. STATE CHANGE;
? для вызова метода digest ( ) класс VirtualPet использует объект Timer вместо метода setlnterval ( );
? жизненный цикл (переваривание пищи) каждого объекта VirtualPet может начинаться и завершаться с помощью методов start ( ) и stop ( );
? метод digest ( ) больше не определяет, умрет ли животное, если оно не будет принимать пищу; он делегирует эту ответственность методу setCalories( );
? формальный метод die ( ) деактивирует объекты VirtualPet.
Руководство по actionscript. часть 7, стр. 028
Внимательно изучите следующие листинги с комментариями. Затем в качестве упражнения попробуйте добавить в зоопарк второе животное.
В листинге П.1 представлен код для класса VirtualZoo, который является основным классом программы.
Листинг П.1. Класс VirtualZoo
package { import flash. display. Sprite: import zoo.*: import flash. events.*:
// Класс VirtualZoo является основным классом приложения. Он расширяет // класс Sprite, благодаря чему его экземпляр может быть создан и добавлен // в список отображения на этапе запуска программы, public class VirtualZoo extends Sprite {
// Экземпляр класс VirtualPet
private var pet-.Virtual Pet:
// Объект, который будет отображать животное на экране private var petView:Vi rtualPetView:
// Конструктор
public function VirtualZoo ( ) { // Создаем новое животное и пытаемся присвоить ему имя try {
pet = new Virtual Pet(«Bartholomew McGi11i cuddy»): } catch (e:Error) { // Если попытка создать объект VirtualPet вызывает исключение. // данный объект не может быть создан. Таким образом, в этом месте // кода мы сообщаем о проблеме и создаем новый объект с заведомо // допустимым именем. traceC’An error occurred: » + е. message): pet = new VirtualPetC’Stan»):
}
// Создаем объект, который будет отображать животное на экране petView = new VirtualPetView(pet):
// Регистрируем данный объект VirtualZoo для получения уведомления // о завершении процесса инициализации // отображаемого объекта («petView»)
petVi ew. addEventLi stener(Event. COMPLETE. petVi ewCompleteLi stener):
}
// Обработчик события вызывается после завершения процесса // инициализации объекта VirtualPetView (petView)
public function petViewCompleteListener (e:Event):void { // Добавляем представление в список отображения addChild(petView);
// Начинаем жизненный цикл животного
pet. start( );
// Кормим животное
pet. eat(new Sushi( ));
}
}
}
В листинге П.2 продемонстрирован код для класса VirtualPet, экземпляры которого представляют животных в зоопарке.
Руководство по actionscript. часть 7, стр. 029
Листинг П.2. Класс VirtualPet
package zoo { import flash. utils.*; import flash. events.*;
// Класс VirtualPet представляет животное в зоопарке. Он расширяет класс // EventDispatcher. благодаря чему может являться получателем // события в процессе диспетчеризации, public class VirtualPet extends EventDispatcher { // ==СТАТИЧЕСКИЕ КОНСТАНТЫ==
// Типы событий, относящиеся к классу VirtualPet (обрабатываемые // объектом VirtualPetView. который отображает животное на экране) public static const NAME_CHANGE:String = «NAME_CHANGE»; public static const STATE_CHANGE;String = «STATE_CHANGE»;
// Состояния, представляющие текущее физическое состояние животного public static const PETSTATE_FULL:int = 0; public static const PETSTATE_HUNGRY:int = 1; public static const PETSTATE_STARVING:int = 2; public static const PETSTATE_DEAD:int = 3;
// ==СТАТИЧЕСКИЕ ПЕРЕМЕННЫЕ==
// Максимальная длина имени животного
private static var maxNameLength:int = 20;
// Максимальное количество калорий, которое может иметь животное
private static var maxCalories:int = 2000;
// Скорость, с которой животное переваривает пищу
private static var caloriesPerSecond:int = 100;
// Имя для животного, используемое по умолчанию
private static var defaultName:String = «Unnamed Pet»;
// ==ПЕРЕМЕННЫЕ ЭКЗЕМПЛЯРА ==
// Имя животного
private var petName:String;
// Текущее количество калорий в «желудке» животного, private var currentCalories:int: // Текущее физическое состояние животного private var petState:int;
// Таймер для вызова метода digest( ) на регулярной основе private var digestTimer:Timer;
// Конструктор
public function VirtualPet (name:String):void { // Присваиваем имя этому животному setName(name);
// Даем этому животному половину от максимально возможного количества // калорий (полупустой «желудок»). setCalori es(Vi rtualPet. maxCalori es/2);
}
// Начинает жизненный цикл животного public function start ( ):void {
// Вызываем метод digestTimerl_istener( ) один раз в секунду
digestTimer = new TimerdOOO. 0);
digestTimer. addEventListener(TimerEvent. TIMER. digestTimerListener); digestTimer. start( );
}
// Останавливает жизненный цикл животного public function stop ( ):void { if (digestTimer!= null) { digestTimer. stop( );
}
}
// Присваивает имя животному и уведомляет приемники об изменении public function setName (newName:String):void { // Генерируем исключение, если новое имя не является допустимым if (newName. indexOfC «) == 0) {
throw new VirtualPetNameException( ); } else if (newName == «») {
throw new VirtualPetInsufficientDataException( ); } else if (newName. length > VirtualPet. maxNameLength) { throw new VirtualPetExcessDataException( );
}
// Присваиваем новое имя petName = newName;
// Уведомляем приемники об изменении имени
di spatchEvent(new Event(Vi rtua1 Pet. NAME_CHANGE));
}
// Возвращает имя животного public function getName ( ):String { // Если животному не было присвоено допустимое имя… if (petName == null) { // …возвращаем имя. используемое по умолчанию return Virtual Pet. defaultName; } else {
// …в противном случае возвращаем имя животного return petName;
}
}
// Добавляет некоторое количество калорий в желудок животного. // используя объект Food public function eat (foodltem:Food):void { // Если животное умерло, ничего не делаем if (petState == Virtual Pet. PETSTATE_DEAD) { trace(getName( ) + » is dead. You can’t feed it.»); return;
}
// Если пищей является яблоко, проверяем его на наличие червей. // Если яблоко червивое, не будем его есть, if (foodltem is Apple) { if (Apple(foodltem).hasWorm( )) { traceCThe » + foodltem. getName( ) + » had a worm. » + getName( )
+ » didn’t eat it.»); return;
}
}
// Отображаем отладочное сообщение с информацией об употребленной пище trace(getName( ) + » ate the » + foodItern. getName( )
+ » (» + foodItem. getCalories( ) + » calories).»); // Добавляем калории из пищи в «желудок» животного setCalori es(getCalori es( ) + foodItem. getCalories( ));
}
// Присваивает животному новое количество калорий и при необходимости // изменяет его состояние
private function setCalories (newCurrentCalories:int):void { // При необходимости корректирует значение newCurrentCalories // в соответствии с допустимым диапазоном if (newCurrentCalories > VirtualPet. maxCalories) {
currentCalories = VirtualPet. maxCalories; } else if (newCurrentCalories < 0) {
currentCalories = 0; } else {
currentCalories = newCurrentCalories;
}
// Определяем количество калорий в желудке животного, в процентах
// от максимально допустимого количества калорий
var caloriePercentage:int = Math. floor(getHunger( )*100);
// Отображаем отладочное сообщение, информирующее о текущем количестве // калорий у животного
trace(getName( ) + » has » + currentCalories + » calories»
+ » (» + caloriePercentage + «% of its food) remaining.»):
// При необходимости устанавливаем состояние животного в зависимости // от изменения в количестве калорий if (caloriePercentage == 0) { // У животного не осталось пищи. Поэтому, если оно еще не умерло… if CgetPetStateC ) != Virtual Pet. PETSTATE_DEAD) { // …деактивируем его die( ); } •
} else if (caloriePercentage < 20) { // животному срочно требуется пища. устанавливаем его состояние // в «ужасно голодный».
Руководство по actionscript. часть 7, стр. 030
If CgetPetStateC ) != Virtual Pet. PETSTATE_STARVING) { setPetState(Vi rtualPet. PETSTATE_STARVING);
}
} else if (caloriePercentage < 50) { // животному требуется пища. устанавливаем его состояние // в «голодный».
if CgetPetStateC ) != Virtual Pet. PETSTATE_HUNGRY) { setPetStateCVi rtualPet. PETSTATE_HUNGRY);
}
} else {
// Животному не требуется пища. Устанавливаем его состояние // в «сытый».
Руководство по actionscript. часть 7, стр. 031
If CgetPetStateC ) != VirtualPet. PETSTATEJULL) { setPetStateC Virtual Pet. PETSTATEJULL);
}
}
// Возвращает количество калорий в «желудке» животного public function getCalories ( ):int { return currentCalories;
}
// Возвращает количество с плавающей запятой, описывающее количество // пищи, оставшееся в «желудке» животного, в процентах public function getHunger ( ):Number { return currentCalories / VirtualPet. maxCalories;
}
// Деактивирует животное private function die ( ):void {
// Останавливаем жизненный цикл животного
stopC );
// Переводим животное в состояние «мертвый» setPetStateCVi rtualPet. PETSTATE_DEAD);
// Отображаем отладочное сообщение, информирующее о смерти животного
• trace(getName( ) + » has died.»);
}
// Уменьшает количество калорий животного в соответствии со скоростью // переваривания пищи этого животного. Этот метод вызывается // автоматически объектом digestTimer. private function digest ( ):void {
trace(getName( ) + » is digesting…»);
setCalories(getCalories( ) — VirtualPet. caloriesPerSecond);
}
// Присваивает целое число, представляющее текущее
// физическое состояние животного
private function setPetState (newState:int):void {
// Если состояние животного не изменилось, выходим из метода
if (newState == petState) { return;
}
// Присваиваем новое состояние petState = newState;
// Умедомляем приемники об изменении состояния животного dispatchEvent(new Event(Vi rtualPet. STATE_CHANGE));
}
// Возвращает целое число, представляющее текущее // физическое состояние животного public function getPetState ( ):int { return petState;
}
// Приемник события для объекта Timer, который управляет // процессом переваривания пищи
private function digestTimerListener (e:TimerEvent):void { // Перевариваем часть пищи digest( );
}
}
}
В листинге П. З представлен код для класса Food, который является суперклассом для различных видов пищи, поедаемой животным.
Руководство по actionscript. часть 7, стр. 032
Листинг П. З. Класс Food
package zoo {
// Класс Food является суперклассом для различных видов пищи, // поедаемой животными, public class Food {
// Хранит количество калорий, которым обладает данный кусок пищи
private var calories:int;
// Удобочитаемое название данного куска пищи
private var name.-String;
// Конструктор
public function Food (initialCalories:int) { // Сохраняем указанное первоначальное количество калорий setCal ori es(i ni ti alCalori es);
}
// Возвращает количество калорий, которым обладает данный кусок пищи public function getCalories ( ):int { return calories;
}
// Присваивает количество калорий, которым обладает данный кусок пищи public function setCalories (newCalories:int):void { calories = newCalories;
}
// Возвращает удобочитаемое название данного куска пищи public function getName ( ):String { return name;
}
// Присваивает удобочитаемое название данному куску пищи public function setName (newName:String):void { name = newName;
}
}
}
В листинге П.4 продемонстрирован код для класса Apple, который представляет конкретный вид пищи, принимаемой животным.
Руководство по actionscript. часть 7, стр. 033
Листинг П.4. Класс Apple
package zoo { // Класс Apple представляет один из видов пищи. // принимаемой животным public class Apple extends Food {
// Количество калорий в объекте Apple, если не указано другое
private static var DEFAULT_CALORIES:int = 100;
// Хранит информацию о том. является ли
// данный объект Apple червивым
private var wormlnApple:Boolean;
// Конструктор
public function Apple (initialCalories:int = 0) { // Если не было указано допустимое количество калорий… if (initialCalories <= 0) {
//…присваиваем данному объекту Apple количество калорий //по умолчанию initialCalories = Applе. DE FAULT_CALORIES;
}
// Случайным образом определяем, будет ли данный объект Apple червивым
// (50 % вероятность)
wormlnApple = Math. random( ) >= .5;
// Присваиваем название этому куску пищи setName(«Apple»);
}
// Возвращает значение типа Boolean, которое сообщает о том. является ли // данный объект Apple червивым public function hasWorm ( ):Boolean { return wormlnApple;
}
}
}
Наконец, в листинге П.5 продемонстрирован код для класса Sushi, который представляет конкретный вид пищи, принимаемой животным.