На этапе проектирования управление в Action Script предполагает, что каждая движущаяся деталь имеет свою программу, т.е. совокупность взаимодействующих объектов построенных из набора классов. Первый шаг в написании новой программы заключается в определении классов. На первом этапе работы каждому логическому классу были присвоены имя и роль в создаваемой программе: герой: арбалет, арбалет сбоку, герой, голова героя сбоку, левая рука сбоку, правая рука сбоку, стрела; мир: дверь, замок, земля, облака, фон;монстры: бот. Некоторые объекты были нарисованы в самом графическом редакторе, а другие - экспортированы (например арбалет, герой, рука, стрела, скелет и его анимация). Каждый класс с помощью кода описывает характеристики и поведение определенного типа объекта. Для корректной работы программы и во избежание совпадения имен с именами, занесенными в базу программы, создается основной пакет, в котором прописываются исходные данные, позволяющие этой игре существовать. В программе создан один пакет GameСlass, предоставленный единым исходным кодом.
Перед началом работы приложения импортируются следующие события: анимация фона, обработка событий мыши, анимация героя, анимация ботов. Также описываются следующие объекты: герой; бот; дверь; массив стрел; массив ботов; счетчик убитых ботов; переменная, хранящая время запуска игры. При запуске создается конструктор, в котором создаются массив стрел и массив ботов, герой, дверь и боты, а также устанавливается покадровый вызов функции проверки столкновений. После этого включается герой и в соответствующую переменную записывается время запуска игры.
В программе основное предпочтение отвелось оператору цикла for для просмотра массива ботов и массива стрел и условному оператору if. Другие традиционные операторы типа while и switch не были использованы, так как основной акцент ставился на попадание стрелы в противника или, соответственно, промах.
Проверку попадания стрел в ботов осуществляет функция testCollision(event:Event):void. Выбирается первый элемент из массива ботов, для которого проверяется попадание в него стрелы последовательно для каждого элемента соответствующего массива.
Если стрела летит (if(mArrayArrows[i].isEnabled())) осуществляется проверка на попадание ее конца в прямоугольник бота (if(mArrayBots[k].hitTestPoint(mArrayArrows[i].x, mArrayArrows[i].y, true)). Если последнее условие выполняется, бот прорисовывается в одном цвете:
var botBD:BitmapData = new BitmapData(mArrayBots[k].width, mArrayBots[k].height);
botBD.draw(mArrayBots[k]).
Далее переменной gettedPixel:uint присваивается цвет пикселя координаты конца стрелы-botBD.getPixel(mArrayArrows[i].x-mArrayBots[k].x,mArrayArrows[i].y-ArrayBots[k].y).
Если стрела попала в бота (цвет не черный и не белый): botBD.getPixel(mArrayArrows[i].x-mArrayBots[k].x, mArrayArrows[i].y-mArrayBots[k].y), - уменьшается жизнь бота на единицу: mArrayBots[k].damage(mArrayArrows[i].getSpeed()/2.5). В случае, если стрела попала в голову: if((mArrayArrows[i].y-mArrayBots[k].y)<30), - бот умирает: mArrayBots[k].damage(mArrayArrows[i].getSpeed()/1.3)
Далее происходит выключение стрелы и удаление ее из массива:
mArrayArrows[i].disable();
mArrayArrows[i].parent.removeChild(mArrayArrows[i]);
mArrayArrows.splice(i, 1)
Если бот мертв: if(mArrayBots[k].isDead), - он также удаляется из массива: mArrayBots.splice(k, 1). Помимо этого увеличивается счетчик убитых и изменяется текст количества убитых:
killed++;
mDoor.panel.killedtxt.text = killed;
а также завершается выполнение цикла обхода стрел и программа переходит к просмотру следующего бота из соответствующего массива.
Если же цвет пикселя конца стрелы черный или белый, получаются координаты центра стрелы:
var tmpx:Number = mArrayArrows[i].width/2*Math.cos(mArrayArrows[i].rotation);
var tmpy:Number = mArrayArrows[i].width/2*Math.sin(mArrayArrows[i].rotation);
и выполняются все те же действия для конца стрелы, описанные выше, но только для ее середины.
Создание бота осуществляет функция mNewBot():void:
private function mNewBot():void
{mBot = new GameClass.Bots(mDoor); // создаем нового бота
mArrayBots.push(mBot); // добавляем бота в массив
// начальная позиция
mBot.x = 620;
mBot.y = 290+Math.random()*20;
parent.addChild(mBot); // добавляем на сцену
mBot.startWalk(); // бот начинает идти
setTimeout( this.mNewBot, 3000+Math.random()*1000 +3000/(getTimer()-startTime) );}
Последняя строка обеспечивает вызов функции себя самой через определенное время: чем больше прошло времени с начала запуска игры, тем чаще будет появляться бот.
Полный код программы с подробными комментариями содержится в приложении.
Тестирование продукта проводилось следующим образом: запускалось приложение, и проводилась проверка на выполнение поставленной задачи. Если поставленная задача не выполнялась, осуществлялся поиск причины ошибок в соответствующем блоке программы.
Одной из первых трудностей, вставших перед разработчиками, являлась обработка попадания стрелы в бота: при высокой скорости полета стрела не убивала бота вообще. Дело в том, что разработанная нами функция на начальном этапе обрабатывала лишь координаты конца стрелы. Вызов функции происходит покадрово. В связи с этим она не успевала обработать тот кадр, когда конец стрелы попадал в прямоугольник бота. Решение пришло само собой: обработка координаты середины стрелы позволило решить эту проблему.
Немало сил было потрачено и на анимацию движения рук стрелка: руки перемещались вверх-вниз как-то неестественно. Но путем многократной переработки был выбран наиболее подходящий вариант.
То же самое получилось и с траекторией полета стрелы. Всем известно, что стрела, как и любой другой предмет, летит по параболе. Траекторию полета, естественно, рассчитать было не трудно. Основная трудность заключалась в другом. Необходимо было поставить в соответствие траекторию движения силе, с которой запускается стрела. Эта проблема решалась так же, как и предыдущая - методом рассмотрения различных вариантов. В результате необходимое соответствие было достигнуто