b5ab525c

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



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

Небольшой клип "actions" помешается за пределами рабочего поля и контролирует процесс игры путем обращения к функциям главной временной шкалы. Она запускает игру при загрузке и вызывает ряд функций в каждом кадре.

onClipEvent(load) {
_root.initGame();
onClipEvent(enterFrame) {
_root.newBalloon() ;
_root.moveBalloons() ;
_root.moveFox();
_root.moveBullets();
}

Функция initGame задает все основные переменные, используемые в игре.

function initGame() {
// Инициализируем переменные, связанные с объектами-шарами.
nextBalloonTime = 0;
nextBalloon = 0;
balloons = [];
numBalloons = 10;
// Инициализируем переменные,
nextBulletTime = 0;


nextBullet = 0;
bullets = [];
// Количество очков равно 0.
score = 0;
}

Перед созданием нового шара необходимо провести три проверки. Первая определяет, остались ли в игре шары, вторая- прошло ли достаточно времени после создания предыдущего шара. Последняя проверка представляет собой своего рода игру "орел и решка": новый шар создается с вероятностью 50%.
После завершения проверок функция newBalloon создает новый шар с 50-процентной возможностью появления шара с левой или правой стороны. Скорость шара принимает произвольное значение от 3 до 5. Число является положительным, если шар будет пролетать слева направо и отрицательным в противном случае.
Цвет нового шара выбирается из пяти возможных оттенков. Для задания цвета используется функция setTransform.
Клипы шаров можно упорядочить, поместив их имена и значения скоростей в массив balloons.
Затем задаются переменные nextBalloon и nextBalloonTime, при помощи которых осуществляется обращение к переменной newBalloon.

function newBalloon () {
// Определяем, могут ли появиться новые шары,
if (nextBalloon < numBalloons) {
// Проверяем, пришло ли достаточно времени
// после появления последнего шара,
if (getTimerO > nextBalloonTime) {
// "Бросаем монетку",
if (Math.Random() "balloon"+nextBalloon,
// Создаем новый шар.
attachMovie("balloon", nextBalloon);
// Выбираем, с какой стороны
// и с какой скоростью полетит шар.
if (Math.Random() _root["balloon"+nextBalloon]._x = -30;
dx = int(Math.Random()*3)+3;
} else {
_root["balloon"+nextBalloon]._x = 580;
dx = -int(Math.Random()*3)-3;
// Выбираем высоту.
_root["balloon"+nextBalloon]._y = int(Math.Random()*100)+20;
// Выбираем цвет.
balloonColor = new Color("balloon"+nextBalloon)
r = int(Math.Random()*5)+1;
if (r == 1) {
balloonColor.setTransform({rb:255}) ;
} else if (r == 2) {
balloonColor.setTransform({gb:255}) ;
} else if (r == 3) {
balloonColor.setTransform({bb:255}) ;
} else if (r == 4) {
balloonColor.setTransform({rb:255,gb:255});
} else if (r == 5) {
balloonColor.setTransform({rb:255,bb:255});
}
// Добавляем новый шар.
balloons.push({clip:"balloon"+nextBalloon,d:dx});
// Изменяем значение переменных.
nextBalloon++;
nextBalloonTime = getTimerf) + 2000;
}}
}}

Созданные шары перемещаются на опрелеленное расстояние с помощью функции moveBalloons. Если шар достиг противоположной границы рабочего поля, его клип удаляется. Соответствующий элемент также удаляется из массива balloons.

Чтобы быстро задать 50-процентную вероятность, лучше использовать фрагмент кода (Math. Random ()
Имейте в виду, что в цикле for функции moveBalloons перечисление осуществляется в обратном порядке: начинается с последнего элемента в массиве balloons и заканчивается 0. Благодаря этому удаление элемента не влияет на остальную часть массива. Предположим, из массива, состоящего из пяти элементов, был удален третий элемент. Тогда четвертый элемент становится третьим, а пятый - четвертым. Если бы вы считали в прямом направлении, вы бы пропустили третий элемент и сразу перешли к четвертому. При счете в обратном порядке такой проблемы не возникает.

Функция moveBalloons проверяет, все ли шары созданы и все ли шары исчезли, что говорит об окончании игры.

function moveBalloons() {
// Перемещаем все шары,
for(i=balloons.length-1;i>=0;i--) {
// Определяем скорость шара
//и получаем ссылку на клип,
dx = balloons[i].d; balloon = _root[balloons[i].clip];
// Перемещаем шар.
balloon._x += dx;
// При вылете за экран шар удаляется,
if ((dx < 0) and (balloon._x < -20)) {
balloon.removeMovieClip() ;
balloons, splice (i,l);
} else if ((dx > 0) and (balloon._x > 570) balloon.removeMovieClip();
balloons.splice(i,1);
// Если шары закончились, игра завершается.
if ((nextBalloon >= numBalloons) and (balloons.length < 1)){
gotoAndStop("game over");
}}

Функция moveFox определяет, нажаты ли клавиши со стрелками «влево» или "вправо", и перемешает лису на 10 пикселов влево или вправо при нажатии соответствующей клавиши. Как и в предыдущих играх, параметр _xscale клипа, содержащего лису, используется для поворота лисы. Функция также задает переход клипа к анимационной последовательности (изображает идущую лису и начинается в кадре 2), а также к кадр (изображает стоящую лису).

function moveFox () {
// Подвинуть лису влево.
if (Key.isDown (Key.LEFT)) {
dx = -10;
fox._xscale = Math.abs(fox._xscale);
// Подвинуть лису вправо, перевернув ее клип по вертикали.

То есть изменив знак у свойства _scale, мы создаем зеркальное отражение клипа; лиса теперь идет в другую сторону.

}else if (Key.isDown(Key.RIGHT)) { dx = 10;
fox._xscale = -Math.abs(fox._xscale);
// Иначе лиса не двигается.
} else {
dx = 0;
// Перемещаем лису.
fox._x += dx;
if ((dx == 0) and (fox._currentFrame != 1)) {
// Переходим к кадру, в котором лиса стоит,
fox.gotoAndStop(1);
} else if ((dx != 0) and (fox._currentFrame == 1)) {
// Переходим к кадру, где лиса бежит.
fox.gotoAndPlay(2);
}
}

Для того чтобы выстрелить, пользователь должен нажать на клавишу пробела. На нажатие клавиши реагирует скрытая кнопка, которая вызывает функцию shootBullet. Код кнопки будет рассмотрен далее, в разделе "К сведению".
Функция shootBullet проверяет, прошло ли достаточно времени после предыдущего выстрела. Это не дает игроку возможности стрелять залпом по всем мишеням.
Подобно шарам снаряды представлены одновременно клипом и элементом массива, в данном случае массива bullets. Массив используется функцией moveBullets для осуществления выстрелов.
Обратите внимание, что движение клипа, содержащего снаряд, начинается в точке, расположенной в 2 пикселях вправо и 55 пикселях влево от центра клипа лисы. Эта точка соответствует кончику соломинки.

function shootBullet () {
// Проверяем, что с момента
// предыдущего выстрела прошло достаточно времени.
if (getTimerO > nextBulletTimei {
// Создаем новую пулю.
attachMoviet"bullet", "bullet'4nextBullet,nextBullet+9999) ;
// Устанавливаем ее координагы.
_root ["bullef+nextBullet] ._jc = fox._x+2;
_root [ "bullef+nextBullet] ._y = fo.x._y-55;
/ / Добавляем новую пулю к массиву.
bullets.push(nextBullet) ;
// Изменяем значение переменных, отвечающих
//за появление пуль.
nextBullet++;
nextBulletTime = getTimer()+1000;
}}

Функция moveBullets работает аналогично функции moveBalloons, но перемещает снаряды не вправо и влево, а вверх. Она проверяет одно из следующих условий: снаряд достиг верхнего края экрана либо попал в шар и вызвал функцию checkCollision. В обоих случаях и клип, и элемент массива удаляются.

function moveBullets () {
/7 Проверяем, попали ли пули в шар.
for(i=bullets.length-1;i>=O;i--) {
// Выбираем элемент.
bullet = _root["bullet"+bullets[i]];
// Передвигаем пулю вверх,
bullet._y -= 10;
// Выясняем, достигла ли она конца экрана,
if (bullet._у < 0) {
bullet.removeMovieClip();
bullets.spliced,1) ;
// Определяем, не попал ли игрок по шару.
} else {
if (checkCollision(bullet)) {
bullet.removeMovieClip();
bullets.splice (i,1);
}}
}}

Функция checkCollision (она будет рассмотрена далее) проверяет все шары и определяет, не находится ли один из них вблизи данного снаряда. При помощи функции distance оценивается расстояние от центра снаряда до центра шара. Если расстояние составляет менее 10 пикселов, что приблизительно равно диаметру шара, выстрел засчитывается как удачный. В клипе шара происходит переход к кадру 2, элемент массива, связанный с шаром, принимает значение true, а функция moveBullet получает команду на удаление снаряда.

Почему для определения попадания используется функция distance, а не hitTest? Причина в том, что функция hitTest выдает значение true в случае, если снаряд попадет в любую часть шара, в том числе и в нитку, которая его держит

function checkCollision(bullet) {
// Просматриваем все шарики,
for(j =balloons.length-1;j >=0;j--) {
balloon = __root[balloons!j].clip];
// Проверяем, попала ли пуля.
if (distance(bullet,balloon) < 10) {
// Переходим к кадру, в котором шар взрывается.
balloon.gotoAndPlay(2);
// Убираем шар из массива,
balloons.splice(j,1);
// Увеличиваем счет,
score += 1;
// Возвращаем значение true,
return(true);
// Если игрок не попал, возвращаем значение false,
}}
return(false);
}

Для определения точного расстояния в пикселях между двумя клипами функция distance использует математическую формулу. Прежде всего, она определяет значение разницы координат клипов по горизонтали и вертикали и сохраняет это значение в переменных dx и dy. Затем вычисляет квадратный корень суммы квадратов данных значений. Формула приведена ниже.

function distance(clipl, clip2) {
// Определяем расстояние между клипами,
dx = clipl._х - clip2._x;
dy = clipl._y - clip2._y;
return (Math.sqrt(dx*dx+dy*dy));
}



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

Некоторые функции данной игры аналогичны функциям игры "Стрельба по воздушным шарам", поэтому нет смысла рассматривать их повторно. Это функции initGame, newBalloon, moveBalloons, checkCollision и distance.
Одна из новых функций в анализируемой игре - aimStraw. Она заменит функцию moveFox и будет вызываться из клипа "actions", которому назначен следующий код:

onClipEvent(load) {
root.initGame();
onClipEvent(enterFrame) {
_root.newBalloon ();
_root.moveBalloons() ;
_root.aimStraw();
_root.moveBullets() ;
}

Задача функции aimStraw - вычислить угол прицела и затем задать поворот клипа соломинки. Значение угла сохраняется в переменной strawRadians, которая используется функцией shootBullet. Для того чтобы вычислить угол между двумя точками, прежде всего необходимо определить значение разницы между горизонтальными и вертикальными координатами точек. Они хранятся в переменных dx и dy функции. Задав эти значения в функции Math.atan2, вы получите значение угла в радианах.

Углы измеряются в радианах или градусах. Полный круг в радианах будет равен 6,28 (2Pi), в градусах - 360. Радианы используются Flash в математических функциях наподобие Math.sin и Math.cos, а градусы - в параметрах клипов „rotation. Поэтому вы должны уметь преобразовывать значения из одних единиц измерения в другие.

Функция Math.atan2 является прекрасным инструментом для программирования игр. Арктангенс (во Flash - Math.atan) представляет собой функцию, вычисляющую угол наклона линии. Так как такой наклон определяется двумя точками, с помощью арктангенса можно преобразовать координаты этих точек в значение угла наклона. Однако при использовании арктангенса не учитывается, какая точка линии является анкером, а какая указателем, задающим угол. Поэтому легко получить углы, противоположные по значению тем, которые вам необходимы. Для того чтобы учесть различные варианты, необходимо написать несколько условных выражений. Функция Math.atan2 (y,x) вычисляет угол наклона линии между началом координат и точкой с координатами (х, у,). Тем самым решается проблема неоднозначности.

function aimStraw() {
// Определяем разницу координат начала
//и конца линии.
dx = _xmouse - straw._x;
dy = _ymouse - straw._y;
// Вычисляем угол наклона.
strawRadians = Math.atan2(dy,dx);
// Переводим полученное значение в градусы.
strawDegrees = 360*strawRadians/(2*Math.PI);
straw._rotation = strawDegrees;
}

Теперь при запуске пули в массив bullets будет записано больше информации. Чтобы осуществлять перемещение объекта-пули в каждом кадре, нам необходимо знать угол, под которым он был выпущен.
К каждому объекту массива bullets будет добавлен параметр down, описывающий силу гравитации, действующую на пулю. Исходное значение этого параметра - 0.
Для того чтобы пуля вылетала из кончика соломинки, ее координаты должны иметь значение, равное значению координат соломинки плюс 20 пикселов (длина соломинки чуть больше 20 пикселов). Эти пикселы необходимо распределить (найти значения катетов при заданной гипотенузе и у угле) между координатами х и у при помощи функций Math.sin и Math.cos для того, чтобы получить горизонтальную и вертикальную стороны угла.

Функции Math.sin и Math.cos используются здесь для определения горизонтальной и вертикальной сторон угла. Для того чтобы наглядно представить это, возьмем круг, центр которого находится в точке 0,0; крайняя верхняя точка имеет координаты 0, -1(система координат, в которой ось Y направлена вниз); крайняя правая - 1,0. Задав в функции Math.sin любой угол, вы получите координату y этого угла на окружности. Функция Math.cos позволяет вычислить координату х. Таким образом, значение Math, sin (0) будет равно (-1), значение Math.cos (0) - 0, что соответствует координатам 0, -1.
Более важно понять то, что перемещение имеет две составляющие: скорость и угол. Значения расстояний для монитора компьютера не могут быть заданы по диагонали, они задаются только по вертикали и горизонтали. Функции Math, sin и Math.cos позволяют преобразовать значения скорости и угла в расстояние по горизонтали и вертикали.

function shootBullet () {
// Проверяем, можно ли выстреливать следующую пулю,
if (getTinerO > nextBulletTime) {
// Создаем пулю.
attachMovie("bullet","bullet"+nextBullet, L.nextBullet+9999);
bullet = _root["bullet"+nextBullet];
// Устанавливаем координаты.
bullet._x = straw._x + Math.cos(strawRadians)*20;
bullet._y = straw._y + Math.cos(strawRadians)*20;
// Добавляем в массив информацию о пуле:
// clip = название клипа,
// angle = начальный угол,
// down = эффект гравитации.
bullets.push({clip:bullet.angle:strawRadians,down:0}
// Увеличиваем счетчик пуль.
nextBullet++;
nextBulletTime = getTimer()+1000;
}}

Функция moveBullets использует параметры angle и down каждого снаряда для перемещения их на определенное расстояние. Кроме этого параметр down увеличивается, чтобы создавался эффект гравитации.
Так как запушенный снаряд должен снова упасть на землю, прежде чем удалить его клип из массива, необходимо проверить, достиг ли он нижнего края экрана.

function moveBullets() {
// Перемещаем все снаряды.
for(i=bullets.length-1;i >=0;i —) {
// Определяем название клипа,
bullet = bullets[i].clip;
// Перемещаем клип.
bullet._x += Math.cos(bullets[i].angle)*10;
bullet._y += Math.sin(bullets[i].angle)*10;
// Добавляем искажение траектории
// из-за воздействия гравитации.
bullet._у += bullets[i].down;
// Увеличиваем значение параметра гравитации,
bullets[i].down += .2;
// Выясняем, достигла ли пуля земли,
if (bullet._у > 400) {
bullet.removeMovieClip();
bullets.splice(i,1);
// Определяем, есть ли попадение.
} else {
if (checkCollision(bullet)) {
bullet.removeMovieClip();
bullets.spliced(i, 1) ;
}}
}}





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

Клип "actions" такой же, как в первой игре этой главы, за исключением того, что новые шарики не создаются в каждом кадре.

onClipEvent(load) {
_root.initGame();
onClipEvent(enterFrame) {
_root.moveBalloons();
_root.moveFox();
_root.moveBullets();
}

Функция initGame вызывает функцию createBalloons, чтобы создать группу шариков. Ей не нужно задавать такие переменные, как nextBalloon или создавать массив balloons, поскольку после начала игры новые шарики не создаются.

function initGame() {
// Создаем шарики.
createBalloons О;
// Параметры снарядов.
nextBulletTime = 0;
nextBullet = 0;
bullets = [];
// Переменная счета.
score =0;
}

Функция createBalloons создает 30 шариков в 10 колонках по 3 штуки в каждой. Каждая ссылка на шарик хранится в массиве. Цвет шарику назначается в зависимости от того, в каком он ряду. Каждому шарику придано начальное направление и скорость равная 3.

function createBalloons() {
balloons = new Array();
balloonNum = 0;
// Создаем новый ряд.
forfvar y=0;y for(var x=0;x // Создаем и размещаем новый шарик.
attachMovie("balloon", "balloon"+balloonNum, balloonNum) ;
balloonClip = this["balloon"+balloonNum];
balloonClip._x = x*30+20;
balloonClip._y = y*30+20;
// Добавляем в массив,
balloons, push (balloonClip) ;
// Устанавливаем цвет.
balloonColor = new Color(balloonClip);
if (y == 0) {
balloonColor.setTransform({rb: 255});
} else if (y == 1) {
balloonColor.setTransform({gb: 255});
} else if (y == 2) {
balloonColor.setTransform({bb: 255});
balloonNum++;}
}
// Направление (скорость) шариков.
balloonDirection = 3;
}

Функция moveBalloons двигает все шарики в массиве balloons. Если какой-нибудь из них дотронется до края экрана, то все они меняют направление. Если же какой-нибудь достигнет низа экрана, игра заканчивается.

function moveBalloons() {
// Переменная-флаг изменения направления,
var newDirection = false;
// Просматриваем все шарики,
for(var i=0;i // Передвигаем текущий шарик,
balloons[i]._x += balloonDirection;
// Смотрим, не достиг ли шарик границы экрана.
if ((balloonDirection > 0) and (balloons[i]._x > 530)) {
newDirection = true;
} else if ((balloonDirection < 0) and (balloons[i]._x < 20)) newDirection = true;
// При столкновении с границой экрана
// шарики опускаются и меняют направление.
if (newDirection) {
balloonDirection *= -1;
for(var i=0;i < balloons.length;i++) {
balloons[i]._y += 3;
//He достигли ли шарики земли?
if (balloons[i-l],_y > 300) {
gotoAndStop("game over");
}
}

Все функции для создания лисы и пуль точно такие же, как и в первой игре главы, поэтому их код я здесь приводить не буду. Но функция checkCollision другая, поскольку она должна следить, не случилось ли так, что все шарики уничтожены, и заканчивать игру.

function checkCollision(bullet) {
// Просматриваем все шарики,
for(j=balloons.length-1;j>=0;j—) {
balloon = balloons[j];
// Смотрим не попала ли пуля в шарик,
if (distance(bullet,balloon) < 10) {
// Удаляем шар из массива,
balloons.splice(j,1);
// Переходим в кадр взрыва шарика,
balloon.gotoAndPlay(2);
// Увеличиваем счет, score += 1;
// Если шаров больше нет - игра заканчивается,
if (balloons.length == 0) {
gotoAndStop("game over");
}
// Возвращаем значение true, так как попали в шарик,
return(true);
}}
// Возвращаем false, поскольку попали в шарик,
return(false);
}



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