Создание кода
Создание кода
Как и в большинстве наших игр, все события данной игры запускаются при помощи клипа "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 и показывает насколько и в каком направлении должна переместиться лиса.
Функция Key. is Down () определяет, удерживается ли определенная клавиша в данный момент. Она особенно полезна в играх, где управление осуществляется при помощи клавиатуры. Для задания клавиши используется ее код. Помимо номеров, например 65 для буквы «А», для задания специальных клавиш, таких как стрелка "вверх", могут использоваться константы, в данном случае Key.UP. Коды клавиш приведены в приложении В справочного руководства по ActionScript Flash MX.
Кроме переменной dx, функция задает переменную _xscale клипа лисы. Действительное значение _xscale остается неизменным, но может быть либо отрицательным, либо положительным. В зависимости от этого клип поворачивается, и лиса начинает двигаться в том или ином направлении.
После задания переменной dx клип лисы перемешается на расстояние, соответствующее указанной величине. Затем проверяется, совпадает ли новое положение с левой и правой границами экрана.
Если движение лисы продолжается, а клип лисы неподвижен, задается его переход к кадру "run", чтобы создать впечатление бегущей лисы. С другой стороны, если лиса не двигается, но в то же время и не находится в кадре 1, задается переход клипа к этому кадру, и создается впечатление, будто лиса стоит.
function moveFox() {
// Проверяем, нажаты ли клавиши со стрелками,
if (Key.isDown(Key.RIGHT)) {
dx = 10;
// Поворачиваем лису направо.
fox._xscale = -Math.abs(fox._xscale);
}
else if (Key.isDown(Key.LEFT)) {
dx = -10;
// Поворачиваем лису налево.
fox._xscale = Math.abs(fox._xscale);
} else {
// He двигаемся.
dx = 0;
// Передвигаем лису.
fox._x += dx;
if (fox._x < 30) fox._x = 30;
if (fox._x > 520) fox._x = 520;
// Меняем поведение лисы (стоит или бежит).
if ((dx != 0) and (fox._currentFrame ==1)) {
fox.gotoAndPlay ("run") ;
} else if ((dx == 0) and (fox._currentFrame != 1)) {
fox.gotoAndPlay ("stand");
}
}
Один раз в каждом кадре вызывается функция dropNewapple. Необходимость создания нового яблока определяется тремя вложенными условными выражениями.
Прежде всего проверяется переменная timeSinceLastapple. Условие выполняется только в случае, если ее значение больше 20. Переменная увеличивается на 1 в конце функции.
В следующей проверке определяется, соответствует ли количество упавших яблок общему количеству яблок, которое должно быть сброшено.
Наконец, функция Math.random() задает 10-процентную вероятность того, что яблоко упадет. В результате интервал между падениями двух яблок будет всегда разным.
Для создания нового клипа яблока используется функция attachMovie. Горизонтальное положение ролика выбирается в диапазоне между 30 и 520. Каждый раз при создании нового яблока значение переменной appleSpeed увеличивается.
function dropNewApple() {
// Бросаем яблоко, если прошло достаточно времени,
if (timeSinceLastApple > 20) {
// Бросаем, если не превышено
// предельное количество яблок, которые можно бросить
. if (lastApple < totalApples) {
// Устанавливаем вероятность падения яблока в 10%.
if (Math.random!) < .1) {
// Создаем объект-яблоко.
lastApple++;
attachMovief"apple", "apple"+lastApple, lastApple);
_root["apple"+lastApple]._x = Math.random!)*490+30;
_root["apple"+lastApple]._y = 0;
// Сбрасываем счетчик времени ожидания.
timeSinceLastApple = 0;
// Увеличиваем скорость падения яблока
if (appleSpeed < 10) appleSpeed += .5;
}
}
}
// ЕСЛИ не бросили яблоко, сокращаем время ожидания.
timeSinceLastApple++;
}
Функция, выполняющая перемещение яблок, должна не только изменять их вертикальное положение, но и проверять, упало ли яблоко на землю или в корзину.
Чтобы определить, упало ли яблоко на землю, функция должна проверить, находится ли яблоко ниже нижней границы экрана. Определить попадание в корзину немного сложнее: необходимо установить, соответствует ли расстояние между яблоком и лисой заданному диапазону. Если яблоко находится от лисы на расстоянии в 10 пикселов по вертикали и 25 пикселов по горизонтали, считается, что оно попало в корзину. Имейте в виду, что центр клипа с лисой находится в центре изображения корзины, поэтому положение корзины фактически определяется положением всего клипа с лисой. На Рисунок 9.3 показан прямоугольник, который представляет область попадания.
Создание кода
Код клипа "actions" аналогичен тому, что использовался в игре "Помай яблоко". Изменятся только функции. В функцию initGame было внесено лишь одно изменение: число падающих яблок было увеличено до 50.
Создание кода
Клипу "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;
if (fox._x < 150) fox._x = 150;
if (fox._x > 400) fox._x = 400;
// Увеличиваем скорость движения байдарки
if (riverSpeed < 20) riverSpeed += .5;
}
Скорость игры увеличивается с помощью функции moveFox, в результате байдарка постепенно набирает скорость.
Функция newRock аналогична функции dropNewApplet предыдущей игры и даже немного проще, поскольку при появлении камня выбор ограничен только одним клипом.
function newRock() {
// Проверяем, прошло ли достаточно времени,
if (timeSinceLastRock > 5) {
// Проверяем, превышено ли максимальное число камней
if (lastRock < totalRocks) {
// Новая скала появляется с вероятностью 10%
if (Math.random() < .1) {
// Создаем новую скалу
lastRock++;
attachMovie( "rocks", "rock"+lastRock, lastRock );
_root["rock"+lastRock]._x = Math.random()*250+150;
_root["rock"+lastRock]._y = 450;
// Решаем, какой кадр показать.
f = int(Math.Random()*_root["rock"+lastRock]._totalFrames) + 1;
_root["rock"+lastRock].gotoAndStop(f);
// Сбрасываем счетчик времени
//до появления следующего камня.
timeSinceLastRock = 0;
// Запоминаем, что с новым камнем
// столкновений не было.
_root["rock"+i].hit = false;
}
} }
// Уменьшаем время до появления следующего камня
timeSinceLastRock++;
}
Обратите внимание, что для каждого нового камня переменная hit принимает значение false. Это обозначает, что байдарка ни разу не столкнулась с данным камнем. Это условие проверяется функцией moveRock перед тем, как разрешить столкновение. В случае столкновения переменная hit соответствующего клипа принимает значение true и второй раз удариться об этот камень байдарка уже не может.
Обратите внимание, что по сравнению с игрой "Поймай яблоко" меняются и координаты области попадания (столкновения). Столкновение может произойти в области с размерами 60 пикселов по горизонтали и 25 пикселов по вертикали в обе стороны от центра. Эта область примерно соответствует форме байдарки (Рисунок 9.8).
Создание кода
Основная часть кода - это сценарий клипа машины. Он начинается с задания переменной 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.
И наконец, масштаб объекта определяется в соответствии со значением _у. Это означает, что объект становится больше по мере приближения
onClipEvent(enterFrame) {
// Движемся вниз.
this._y += _root.speed;
// Движемся в стороны.
this._x += dx*_root.speed;
// Возвращаем объект на исходную озицию, если он проехал за
// нижнюю границу экрана.
if (this._y > 600) {
this._y = 200;
if (Math.random() < .5) {
// Объект слева.
this._x = Math.random()*170;
dx = -1;
} else {
// Объект справа.
this._x = 550-Math.random()* 170;
dx = 1;
// Задаем масштаб в соответствие со значением
_у. this._xscale = this._y/4;
this._yscale = this._y/4;
}
Обратите внимание, что клип "sideObject" не взаимодействует с машиной. Это делает только клип "bonus". Но объекты по сторонам дороги направляют взгляд игрока так, что создается ощущение глубины.
Центральная линия движется, как и камни, но, поскольку она находится в центре экрана, она не передвигается ни вправо, ни влево. Она просто движется вниз и изменяет масштаб.
onClipEvent(enterFrame) {
// Движемся вниз.
this._y += _root.speed;
// Возвращаемся к горизонту.
if (this._y > 400) {
this._y = 200;
// Устанавливаем масштаб.
this._xscale = this._y/4;
this._yscale = this._y/4;
}
Бонусные звезды ведут себя более похоже на объекты по сторонам. Однако они не появляются где попало. Они появляются с равной вероятностью в одном из двух мест на дороге.
Таким образом, двигаясь вниз по экрану, бонусная звезда движется в сторону со скоростью вполовину меньшей, чем вниз. Это позволяет создавать более точную перспективу, поскольку звезды находятся ближе к центру дороги.
onClipEvent(enterFrame) {
// Движемся вниз.
this._y += _root.speed;
this._x += dx*_root.speed;
// Возвращаемся к горизонту,
if (this._y > 600) {
this._y = 200;
if (Math.random() < .5) {
// Переходим на левую сторону дороги.
this._x = 250;
dx = -.5;
} else {
// Переходим на правую сторону дороги.
this._x = 300;
dx = .5;
}
// Устанавливаем масштаб в соответствии с вертикальным
// положением.
this._xscale = this._y/4;
this._yscale = this._y/4;
}
Клип "actions" расположен вне экрана и содержит игровые часы. Он замечает время начала и производит обратный счет до 0. В клипе-приме игра очень короткая, всего 15 секунд. Вы можете увеличить ее до минуты или двух.
Когда обратный отсчет доходит до 0, главная временная шкала отправляется к кадру "game over". Параметр speed становится равным 0, и машина замирает на месте.
onClipEvent(load) {
// Рассчитываем время окончания игры.
endTime = getTimer()+15000;
onClipEvent(enterFrame) {
// Подсчитываем, сколько времени прошло.
timeLeft = (endTime - getTimer())/1000;
// Конец игры.
if (timeLeft
_root.speed = 0;
_root.timeDisplay = "0";
_root.gotoAndStop("game over");
} else {
// Отображаем оставшееся время.
_root.timeDisplay = timeLeft;
}}
Кроме команды stop () в первом кадре, есть еще только один сценарий временной шкалы - в главном кадре игры. Он перемешает машину на передний план (уровень) экрана, так что центральная линия и бонусные звезды оказываются под ней. Кроме того, короткий цикл дублирует клип "sideObject" 5 раз. Каждой копии придано разное значение _у, поэтому камни не появляются все одновременно.
// Помещаем машину на передний план,
car.swapDepths(999);
// Создаем пять камней.
for(i=0;i
mc = sideobject.duplicateMovieClip("side object"+i,i);
mc._у = 400+Math.random()*200;
}
Содержание раздела