Луноход
Исходный файл: 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 Кадры основной временной шкалы
Кадры
|
Содержание
|
start
|
Содержит введение и кнопку Play, чтобы начать игру
|
start level
|
Предупреждает игрока о начале первого уровня
|
level 1
|
В этом кадре игрок проходит первый уровень, если его корабль останется цел, ролик перейдет к следующему кадру
|
level 1 done
|
Если игрок благополучно закончил первый уровень, ему выдается об этом сообщение, и отображается кнопка Play, с помощью которой можно начать второй уровень
|
level2
|
В этом кадре игрок проходит второй уровень, если его корабль останется цел, ролик перейдет к следующему кадру
|
level2 done
|
Если игрок благополучно закончил второй уровень, ему выдается об этом сообщение, и отображается кнопка Play, с помощью которой можно начать третий уровень
|
level3
|
В этом кадре игрок проходит третий уровень, если его корабль останется цел, ролик перейдет к следующему кадру
|
game over
|
Игрока поздравляют с тем, что он три раза успешно посадил корабль. Кнопка Play предлагает попробовать сделать это еще раз
|
lost ship
|
Если на каком-либо уровне корабль игрока взрывается, ролик переходит к этому кадру, и игра заканчивается. С помощью кнопки Play можно попытаться еще раз пройти игру
|
У вас также будет два простых клипа: "fuel gauge" и "fuel meter". Первый представляет собой пустой прямоугольник, а второй - сплошной. Клип "meter" помещается внутри клипа "gauge". Далее в коде вы укажете,чтобы при сжигании горючего размеры клипа "meter" уменьшались, то есть он будет занимать меньше места в прямоугольнике "gauge".
Создание кода
В трех кадрах "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});
hitPoints.push({x:9, y:13});
hitPoints.push({x:0, y:-10});
hitPoints.push({x:-9, y:-7});
hitPoints.push({x:8, y:-7});
// Определяем координаты опор лунохода
footPoints = new Array();
footPoints.push({x:-9, y:13});
footPoints.push({x:9, y:13});
// Создаем массив из клипов "pad" (посадочная площадка)
pads = new Array();
for (i=0; i<3; i++) {
pads.push(_root["pad"+i]);
}}
В каждом кадре посредством клипа "actions" вызывается функция moveShip, которая, в свою очередь, вызывает множество небольших функций для управления кораблем. Всегда лучше разбивать большой фрагмент кода на несколько небольших функций.
function moveShip() {
shipThrusters();
shipMovement();
checkForLand();
checkForCrash();}
Функция shipThrusters проверяет, осталось ли еще горючее, если нет, то клип "ship" переходит к кадру "normal". В противном случае, если игрок нажимает на одну из клавиш со стрелками "вверх", "влево" или "вправо", включается соответствующий ускоритель. Клип "ship" переходит к соответствующему кадру, и чтобы отразить эффект действия ускорителя, изменяются значения dx и dy. Также уменьшается количество топлива.
function shipThrusters() {
// Проверяем ускорители и корректируем скорость,
if (fuel < 0) {
ship.gotoAndStop("normal");
} else if (Key.isDown(Key.UP)) {
ship.dy -= .4;
ship.gotoAndStop("up");
fuel -= 2;
showFuel();
} else if (Key.isDownfKey.LEFT)) {
ship.dx -= .2;
ship.gotoAndStop("left");
fuel -= 1;
showFuel();
} else if (Key.isDownfKey.RIGHT)) {
ship.dy += .2;
ship.gotoAndStop("right");
fuel -= 1;
showFuel();
} else {
//He включен ни один из ускорителей,
ship.gotoAndStop("normal"); }}
Функция shipMovement изменяет скорость корабля согласно гравитации и перемешает корабль в зависимости от скорости лунохода.
function shipMovement() {
// Гравитация заставляет корабль двигаться вниз,
ship.dy += gravity;
// Перемещаем корабль.
ship._x += ship.dx;
ship._y += ship.dy;}
Функция checkPorLand проверяет массив footPoints: находится ли хоть одна опора лунохода внутри клипа "pad". Если там нет ни одной опоры, переменной landed присваивается значение false. Такое же значение присваивается и в том случае, когда скорость лунохода больше трех единиц, поскольку данная скорость слишком высока для того, чтобы луноход смог совершить посадку.
Если после этого значение переменной landed все еще равно true, значит, луноход удачно совершил посадку. Все, что, теперь необходимо сделать, - перейти к следующему кадру в основной временной шкале и увеличить значение переменной gameLevel на единицу.
function checkForLand() {
// Выясняем, обе ли опоры находятся на посадочной площадке.
landed = true;
for(i=0; i
// Просматриваем все площадки.
footDown = false;
for(j=0; j
// Проверяем, находится ли опора на площадке,
if (pads[j].hitTest(ship._x+footPoints[i].x, ship._y+footPoints[i].y, true)) {
footDown = true;
break;}}
// Если опора не находится на площадке,
// значит, корабль не совершил посадку,
if (!footDown) {
landed = false;
break;}}
// Проверяем, не слишком ли быстра движется корабль.
if (ship.dy > 3.0) landed = false;
if (landed) {
// Посадка совершена. gotoAndPlay(_currentFrame+1);
gameLevel++;
}}
С другой стороны, необходимо проверять, взорвался луноход или нет. В массиве hitPoints содержится список координат точек вокруг корабля: двух опор, середины каждой стороны, вершины и центра днища. Так как невозможно определить, полностью ли один объект накладывается на другой, вы просто проверяете эти точки. Если какая-то из них оказалась внутри элемента "activeground", тогда корабль разбился. У клипа "Ground - level X" на каждом уровне - имя экземпляра "activeground".
function checkForCrash() {
// Корабль не совершил посадку. Проверяем, коснулся ли он
// поверхности Луны,
if (Handed) {
// Просматриваем все возможные точки касания.
for(i=0; i
// Проверяем, не коснулся ли корабль поверхности
// Луны в этой точке.
if (activeground.hitTest(ship._x+hitPoints[i].x, ship._y+hitPoints[i].y, true)) {
ship.gotoAndPlay("explode");
// Уменьшаем количество жизней
// или завершаем игру.
gotoAndPlay("lost ship"); break; }}}}
Еще одна полезная функция в этом ролике - showFuel. Она берет клип "meter" и присваивает его свойству _xscale величину fuel. Так как сначала значение переменной fuel (запас горючего) равно 100, а затем уменьшается до 0, его легко использовать для свойства _xscale. Если бы диапазон значений fuel был другим, вам бы пришлось сначала преобразовать их так, чтобы они находились в диапазоне от 0 до 100, а лишь затем присваивать их свойству _xscale.
function showFuel() {
gauge.meter._xscale = fuel;
}
Обратите внимание: для того чтобы размеры клипа "meter" уменьшались справа налево, необходимо поместить центр клипа так, чтобы
центр прямоугольника располагался справа от него. Если центр клипа окажется слева, то изменение величины _xscale приведет к тому,
что объект будет сокращаться к центру, а не справа налево.
К сведению
В этом ролике к каждой кнопке Play прикреплена одна строчка кода. Просмотрите каждый из этих сценариев, чтобы понять, к какому кадру переходит ролик или какая функция вызывается.
Обратите внимание, что во всех трех типах ускорителей использовалась одна и та же анимация - thrust animation. Для левого и правого ускорителей клип поворачивался на 90° или на -90°. Размер анимации боковых ускорителей был уменьшен, так как предполагается, что они слабее основного ускорителя.
Другие возможности
В этой игре очки не начисляются. Вы же можете добавлять очки за каждую успешную посадку, причем за посадку на труднодоступные посадочные площадки начислять больше обычного. Также можно предоставлять премию за скорость и объем неиспользованного топлива. Добавить уровни к игре очень просто, для этого нужно только нарисовать рельеф. Когда вы исчерпаете все свои идеи, попробуйте изменить код таким образом, чтобы на более высоких уровнях с тем же рельефом корабль имел меньше топлива или была более сильная гравитация.
|