Создание Flash-игр

         

Погоня в лабиринте

Исходный файл: Mazechasе.fla

Следующая игра - "Погоня в лабиринте" - классическая аркадная игра. Самое известное воплощение этой игры - Рас-Man.
В игре, фрагмент которой изображен на рис. 16.4, лиса бегает в лабиринте, пытаясь съесть все ягоды. Там же бегает злой кролик. Лиса должна не столкнуться с кроликом, пока не соберет все ягоды.

Рисунок 16.4 Лиса пытается собрать все ягоды, в то время как кролик стремится ее догнать

Задача проекта

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

Подготовка ролика

В ролике 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".

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

В первом кадре содержится копия кнопки 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; у<16; у++) {
for (x=l; х<22; х++) {
// Выясняем, расположены ли пересечения поверх фона.
if (!(background.hitTest(x*25,y*25,true))) {
// Создаем и размещаем клип "berry".
attachMovie ("berry", "berry"+level, level);
clip = _root["berry"+level];
clip._x = x*25; clip._y = y*25;
// Добавляем клип в массив berries.
berries.push(clip);
level++;
}}}
// Создаем клип с лисой и определяем его положение.
attachMovie("fox", "fox", level++);
fox._x = 275;
fox._y = 275;
// Определяем направление движения и координаты цели,
fox.move = {x:0; у:0};
fox.dest = {х:275, у:275};
fox.nextmove = 0;
// Создаем и размещаем клип с кроликом.
attachMovie("bunny", "bunny", level++);
bunny._x = 275;
bunny._y = 125;
// Определяем направление движения и координаты цели.
// Запоминаем координаты предыдущего положения,
bunny.move = {х:1, у:0};
bunny.dest = {х:300, у:125};
bunny.nextmove = 0;
bunny.last = {x:275, у:125};
}

В каждом кадре вызывается функция move, которая передвигает клип с лисой в соответствии с объектом move. В функции содержится специальное условие, чтобы можно было определить, перемещается ли лиса за пределы экрана справа или слева, и если да, то лиса появляется на противоположной стороне (по тоннелю лиса может переходить с одной стороны экрана на другую).
Новое положение цели как для лисы, так и для кролика - всегда координаты следующей ягоды. Даже если ягоду не видно, клип все равно находится на своем месте. Когда лиса доходит до ягоды, координаты которой совпадают со значениями объекта fox.dest, вызывается функция eatBerry, чтобы удалить ягоду, если она все еще видна. Затем с помощью функции nextMove определяются координаты следующего положения цели.
Обратите внимание, что лиса каждый раз перемещается на пять пикселов. Так как все ягоды расположены на расстоянии 25 пикселов друг от друга, то, чтобы дойти до следующей ягоды, необходимо сделать пять шагов. Скорость передвижения лисы - число, которое прибавляется к свойству nextMove. В данном случае добавляется число 50, то есть между шагами пройдет, по крайней мере, 50 миллисекунд.

function move() {
// Выясняем, можно ли сделать следующий шаг.
if (getTimert) > fox.nextmove) {
// Нельзя сделать следующий шаг в течение 50 миллисекунд,
fox.nextmove = getTimer() + 50;
// Перемещаем лису.
fox._x += fox.move.x*5;
fox._y += fox.move.y*5;
// Определяем, прошла ли лиса сквозь тоннель,
if (fox._x > 550) fox._x = 0;
if (fox._x < 0) fox._x = 550;
// Проверяем, достигла ли лиса положения своей цели,
if ((fox._x == fox.dest.x) and (fox.__y == fox.dest.у)) {
eatBerry();
nextMove();
}}}

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

function eatBerry() {
// Предположим, что все ягоды были съедены.
allGone = true;
// Просматриваем массив berries,
for (i=0; i<berries.length; i++) {
// Выясняем, находится ли ягода там же, где и лиса.
if ((berries[i]._currentFrame == 1) and (berries[i]._x == fox._x) and (berries[i]._y == fox._y)) {
// Удаляем ягоду.
berries[i].gotoAndStop("nothing");
// Лиса открывает рот.
fox.gotoAndPlay("eat");
// Увеличиваем число очков.
score++;
// Если какая-то ягода еще не съедена,
// то уровень не закончен.
} else if (berries[i]._currentFrame== 1){
allGone = false;
}} // ЕСЛИ все ягоды были съедены, уровень завершен.
if (allGone) {
gotoAndPlay("level over");
gameLevel++;
}}

Когда лиса доходит до ягоды, необходимо определить следующее положение цели. С помощью объекта Key можно проверить все четыре клавиши со стрелками, если нажата одна из них, для лисы определяется
объект move. Однако это не значит, что лиса будет двигаться в указанном направлении.
Для того чтобы лиса могла сделать шаг, необходимо, чтобы в том направлении на расстоянии ровно в 25 пикселов находился клип ягоды.
Если же его там нет, то свойство move объекта обнуляется.

function nextMove () {
// Предположим, что лиса двигаться не будет.
fox.move.х =0;
fox. move, у =0;
// Проверяем клавиши со стрелками.
// Определяем потенциальное направление движения.
// Если нужно, поворачиваем лису влево или вправо.
if (Key.isDownfKey.LEFT)) {
fox.move.x = -1;
fox._xscale = Math.abs(fox._xscale);
} else if (Key.isDown(Key.RIGHT)) {
fox.move.x = 1;
fox._xscale = -Math.abs(fox._xscale);
} else if (Key.isDown(Key.UP)) {
fox.move.у = -1;
} else if (Key.isDownfKey.DOWN)) {
fox.move.у = 1;
}
// Определяем потенциальное положение цели.
newx = fox._x + fox.move.x*25;
new = fox._y + fox.move.y*25;
okToMove = false;
// Просматриваем массив berries: совпадают ли координаты
// потенциального положения цели с координатами какой-либо
// ягоды,
for(i=0;i< berries.length;i++) {
// Совпадение найдено, указываем новое положение цели,
if ((berries[i]._x == newx) and (berries[i]._y == newy)) {
fox.dest.x = newx;
fox.dest.y = newy;
okToMove = true;
}}
// Указываем специальные установки для прохода сквозь тоннель,
if (newx == 550) {
okToMove = true;
fox.dest.x = 25;
} if (newx == 0) {
okToMove = true;
fox.dest.x = 525;}
// Если совпадение не найдено, не перемещаем лису.
if (!okToMove) {
fox.move.x = 0;
fox.move.у = 0;
}}

Кролик двигается непредсказуемо. Когда он доходит до ягоды, следующий фрагмент кода просматривает массив berries и определяет, какие клипы ягод находятся рядом с текущим положением кролика. Затем случайным образом выбирается один из этих клипов, координаты которого и будут положением цели кролика. Не может быть выбрано только то направление, откуда пришел кролик. Другими словами, кролик не может вдруг повернуть назад. Таким образом, кролик идет по длинным коридорам, не останавливаясь и не шарахаясь из стороны в сторону. Однако если кролик заходит в тупик, он может идти в обратном направлении, так как это единственно возможный путь.
И последнее, что делает функция move Bunny, - это проверяет, не находится ли кролик вблизи от лисы. Если да, то кролик ловит лису, и она теряет одну жизнь.

function moveBunny() {
// Проверяем, пришло ли время для следующего шага кролика,
if (getTimert) > bunny.nextmove) {
// Определенное время кролик двигаться не может,
bunny.nextmove = getTimerO + 60 - gameLevel*10;
// Перемещаем кролика.
bunny._x += bunny.move.x*5;
bunny._y += bunny.move.у*5;
// Выясняем, дошел ли кролик до положения цели,
if (bunny._x == bunny.dest.x and bunny._y == bunny .dest .y) {
// Создаем массив с координатами
// возможных положений кролика,
possibilities = new Array;
for (i=0; i // Определяем расстояние между
// текущим положением кролика и ягодой,
xdiff = Math.abs(berries[i]._x - bunny._x);
ydiff = Math.abs(berries[i]._y - bunny._y);
// Если эта ягода находится рядом...
if ((xdiff == 25 and ydiff == 0) or (xdiff == 0 and ydiff == 25) {
// ...тогда ее положение может
// быть положением цели кролика.
possibilities.push(berries[i]);
}} // Среди возможных положений цели выбираем
// произвольное,
do {
r = int(Math.random()*possibilities.length);
// Указываем новое положение цели
//и направление движения.
bunny.dest.x = possibilities[r]._х;
bunny.dest.y = possibilities[r]._y;
bunny.move.х = (possibilities[r]_x - bunny._х)/25;
bunny.move.у = (possibilities[r]._y - bunny._у)/25;
// Принимаем выбранные положения, если кролик
// не возвращается назад или если этот
// путь - единственно возможный.
} while ((bunny.dest.х = lastx and bunny.dest.y == lasty) and (possibilities.length > 1));
// Запоминаем координаты предыдущего положения,
lastx = bunny._x; lasty = bunny._y;
}}
// Проверяем, находится ли кролик поблизости с лисой,
if (Math.abs(bunny._x - fox._x) <= 10 and Math.abs(bunny._y -fox._y) <= 10 { if (lives < 1) { gotoAndStop("game over");
} else {
lives--;
gotoAndStop("lost life");
}}}

К сведению

He забудьте, что нужно присвоить имена связи клипам лисы, кролика и ягоды. Для каждого кадра, в том числе и в небольших клипах, вам понадобится функция stop().

Другие возможности

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


Содержание раздела