Одна из самых популярных флэш-игр — Bloons , в которой вы играете в обезьяну, которая бросает дротики в воздушные шарики. Это породило множество сиквелов, даже разветвляющихся на другие жанры, такие как защита башни. Из этого туториала Вы узнаете, как создать собственную игру с воздушными шариками, используя движок QuickBox2D.
Окончательный результат предварительного просмотра
Давайте посмотрим на конечный результат, к которому мы будем стремиться:
Нажмите и удерживайте, чтобы определить угол выстрела. Попробуй лопнуть все шары!
Шаг 1: Краткий обзор
В этом уроке мы будем использовать серию классов ActionScript для создания игры Bloons Inspired. Цель игры — стрелять по воздушным шарам, чтобы совать их всех.
Шаг 2: Настройки документа Flash
Откройте Flash и создайте документ шириной 480 пикселей и высотой 320 пикселей. Установите частоту кадров 24 к / с.
Шаг 3: Интерфейс
Будет использован красочный и простой интерфейс с несколькими фигурами, кнопками и мувиклипами. В течение следующих нескольких шагов мы создадим этот графический интерфейс. Белка и изображение желудя взято с openclipart.org .
Шаг 4: Фон
Этот фон был создан во Flash с использованием простых прямоугольников и овальных форм. Коричневая полоса внизу будет служить информационной полосой.
Шаг 5: Заголовок и воздушные шары
Чтобы создать заголовок, выберите инструмент «Текст» (T) и измените цвет на #EEEEEE; напишите текст заголовка (я использовал шрифт GoodDog) и добавьте простую тень. Для всплывающего окна выберите инструмент «Овал» (O) и создайте овал размером 20×30 px # FFCE47. Используйте Poly Star Tool для маленького треугольника под ним.
Шаг 6: Кнопки
Снова используйте Text Tool, чтобы создать две кнопки, как показано на рисунке выше. Преобразуйте их в кнопки и дайте им описательные имена экземпляров, чтобы мы могли легко использовать их позже в коде. Преобразуйте графику на сцене в один мувиклип и назовите его TitleView — не забудьте установить флажок « Экспорт для ActionScript» .
Шаг 7: Экран игры
Это игровой экран, который содержит все динамичные и интерактивные элементы игры. Больше из них будет сгенерировано во время выполнения с использованием ActionScript. Вы можете прочитать имена экземпляров на изображении выше.
Шаг 8: Экран кредитов
Экран Credits появится перед экраном Title ; использовать графику и шрифты, прежде чем создать его. Назовите его CreditsView и не забудьте установить флажок « Экспорт для ActionScript» .
Шаг 9: оповещение
Предупреждение будет показано, когда все воздушные шары были выскочил; он будет отображать сообщение об игре и счет. Используйте инструмент Rectangle Tool, чтобы создать его и установить имя его экземпляра в AlertView . Снова отметьте поле « Экспорт для ActionScript» .
Шаг 10: Звуки
Мы будем использовать звуковые эффекты, чтобы улучшить ощущение игры; Вы можете найти звук, используемый в этом примере на Soungle.com, используя ключевое слово pop .
Шаг 11: TweenNano
Мы будем использовать другой движок анимации движения, отличающийся от встроенного во Flash, по умолчанию, это повысит производительность и облегчит использование.
Вы можете скачать TweenNano с официального сайта .
Шаг 12: QuickBox 2D
Мы будем использовать полезную физическую библиотеку QuickBox2D для создания этой игры. Если вы не знакомы с ним, вы можете следовать серии Введение от Activetuts +.
Вы можете скачать QuickBox2D с официального сайта .
Шаг 13: Установите класс документа
Мы сделаем наше приложение интерактивным, используя внешний класс. Добавьте его имя в поле « Класс» в разделе « Публикация » на панели « Свойства», чтобы связать FLA с классом основного документа .
Шаг 14. Создайте новый класс ActionScript
Создайте новый (Cmd + N) класс ActionScript 3.0 и сохраните его как Main.as в папке вашего класса.
Шаг 15: Структура класса
Создайте базовую структуру классов, чтобы начать писать код.
01
02
03
04
05
06
07
08
09
10
11
12
|
package
{
import flash.display.Sprite;
public class Main extends Sprite
{
public function Main():void
{
// constructor code
}
}
}
|
Шаг 16: Обязательные классы
Это классы, которые нам нужно импортировать, чтобы наш класс работал; директива import
делает внешние классы и пакеты доступными для вашего кода.
01
02
03
04
05
06
07
08
09
10
|
import flash.display.MovieClip;
import com.actionsnippet.qbox.*;
import com.greensock.TweenNano;
import com.greensock.easing.Expo;
import flash.events.MouseEvent;
import Box2D.Common.Math.*;
import flash.events.Event;
import flash.net.navigateToURL;
import flash.net.URLRequest;
|
Шаг 17: Переменные
Эти переменные мы будем использовать. Прочитайте комментарии в коде, чтобы узнать больше о них; некоторые из их имен говорят сами за себя, поэтому там не будет никаких комментариев.
01
02
03
04
05
06
07
08
09
10
|
private var titleView:TitleView = new TitleView();
private var credits:CreditsView;
private var world:QuickBox2D;
private var acorn:QuickObject;
private var acorns:Array = [];//stores the acorns thrown
private var contacts:QuickContacts;
private var balloons:Array = [];
private var yImpulse:Number = 0;
private var xImpulse:int = 3;
private var pop:Pop = new Pop();
|
Шаг 18: Конструктор
Конструктор — это функция, которая запускается, когда объект создается из класса, этот код выполняется первым, когда вы создаете экземпляр объекта. Конструктор класса документа является особым случаем: он запускается в начале игры.
Мы используем это для вызова необходимых функций, чтобы начать игру. Проверьте эти функции в следующих шагах.
1
2
3
4
|
public final function Main():void
{
//Code
}
|
Шаг 19: Добавьте заголовок
Мы начнем с добавления TitleView из библиотеки на сцену.
1
2
|
addChild(titleView);
startButtonListeners();
|
Шаг 20: Запустите кнопки прослушивания
Это добавит слушателей мыши к кнопкам в представлении заголовка, что приведет нас к экрану игры или кредитов.
01
02
03
04
05
06
07
08
09
10
11
12
13
|
private final function startButtonListeners(action:String = ‘add’):void
{
if(action == ‘add’)
{
titleView.creditsBtn.addEventListener(MouseEvent.MOUSE_UP, showCredits);
titleView.playBtn.addEventListener(MouseEvent.MOUSE_UP, showGameView);
}
else
{
titleView.creditsBtn.removeEventListener(MouseEvent.MOUSE_UP, showCredits);
titleView.playBtn.removeEventListener(MouseEvent.MOUSE_UP, showGameView);
}
}
|
Шаг 21: Показать кредиты
Экран Credits отображается, когда пользователь нажимает кнопку Credits. Слушатель мыши добавляется в полный MovieClip, чтобы удалить его.
1
2
3
4
5
6
7
8
|
private final function showCredits(e:MouseEvent):void
{
titleView.creditsBtn.visible = false;
titleView.playBtn.visible = false;
credits = new CreditsView();
addChild(credits);
TweenNano.from(credits, 0.3, {x:-credits.width, onComplete:function():void{credits.addEventListener(MouseEvent.MOUSE_UP, hideCredits);}});
}
|
Шаг 22: Скрыть кредиты
Если щелкнуть экран « Кредиты», он вернется и будет удален со сцены.
01
02
03
04
05
06
07
08
09
10
11
12
13
|
private final function hideCredits(e:MouseEvent):void
{
TweenNano.to(credits, 0.3, {
x: -credits.width,
onComplete: function (): void {
titleView.creditsBtn.visible = true;
titleView.playBtn.visible = true;
credits.removeEventListener(MouseEvent.MOUSE_UP, hideCredits);
removeChild(credits);
credits = null;
}
});
}
|
Шаг 23: Показать игровой вид
Следующие строки удаляют титульный экран и оставляют экран игры видимым. Здесь мы также вызываем необходимые функции для запуска игры; эти функции объясняются в следующих шагах.
01
02
03
04
05
06
07
08
09
10
11
12
|
private final function showGameView(e:MouseEvent):void
{
TweenNano.to(titleView, 0.3, {
y: -titleView.height,
onComplete: function (): void {
startButtonListeners(‘rmv’);
removeChild(titleView);
titleView = null;
startGame();
}
});
}
|
Остановимся здесь, чтобы сделать быстрый тест и убедиться, что наш игровой код работает:
Имейте в виду, что некоторые строки были закомментированы, так как некоторые функции еще не созданы.
Помните, что Вехи включены в исходные файлы, поэтому, если по какой-то причине ваш файл не имитирует этот, взгляните на источник, чтобы понять, что его вызывает.
Шаг 24: Слушатели игр
Эта функция добавляет слушателей мыши, необходимых для выполнения съемки желудя.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
private final function gameListeners(action:String = ‘add’):void
{
if(action == ‘add’)
{
bg.addEventListener(MouseEvent.MOUSE_DOWN, startCharge);
bg.addEventListener(MouseEvent.MOUSE_UP, shot);
restartBtn.addEventListener(MouseEvent.MOUSE_UP, restartLvl);
stage.addEventListener(Event.ENTER_FRAME, update);
}
else
{
bg.removeEventListener(MouseEvent.MOUSE_DOWN, startCharge);
bg.removeEventListener(MouseEvent.MOUSE_UP, shot);
restartBtn.removeEventListener(MouseEvent.MOUSE_UP, restartLvl);
stage.removeEventListener(Event.ENTER_FRAME, update);
}
}
|
Шаг 25: Запустите игру
Здесь мы начинаем игру с создания мира Box2D и вызова функций, которые будут создавать воздушные шары и обрабатывать события мыши.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
private final function startGame():void
{
/* Hide gCircle */
gCircle.visible = false;
/* New B2D world */
world = new QuickBox2D(this, {debug:0});
contacts = world.addContactListener();
contacts.addEventListener(QuickContacts.ADD, onAdd);
/* Create balloon function */
gameListeners();
createBalloons();
}
|
Шаг 26: создай воздушные шары
Для размещения воздушных шаров на сцене используются гнезда for
петель. Эта функция будет использовать метод addBox addBox
для создания нового объекта Box2D, который будет установлен как датчик — это означает, что не будет никакой физической реакции на столкновение (то есть желудь не отскочит от него), но столкновение все равно будет быть обнаруженным. Используя этот метод, мы можем уничтожить воздушный шар, но пусть желудь продолжит свой путь, как будто ничего не произошло.
Затем шарик добавляется в массив; это даст нам доступ ко всем шарам вне этой функции.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
private final function createBalloons(h:int = 5, v:int = 3):void
{
for(var i:int = 0; i < h; i++)
{
for(var j:int = 0; j < v; j++)
{
var balloon:QuickObject = world.addBox({x:10 + (i * 0.66), y:4 + (j * 1), width: 0.66, height: 1, skin:Balloon, fixedRotation:true, draggable:false, density:0});
balloon.shape.m_isSensor = true;
balloons.push(balloon);
}
}
/* Set balloon counter */
targetTF.text = String(balloons.length);
/* Start Physics */
world.start();
}
|
Конечно, вам не нужно использовать вложенные циклы для позиционирования воздушных шаров; это самый простой способ расположить их в сетке, но вы можете расположить их вручную, если хотите.
Шаг 27: Обнаружение столкновения
Эта функция обрабатывает столкновение, упомянутое в шаге 26. Первое, что нужно сделать, — это просмотреть массив воздушных шаров, проверяя каждый из них на предмет столкновения с желудем.
1
2
3
4
5
6
|
private final function onAdd(e:Event):void
{
for(var i:int = 0; i < balloons.length; i++)
{
if(contacts.isCurrentContact(balloons[i], acorn))
{
|
Шаг 28: Уничтожь воздушный шар
Если столкновение истинно, мы вызываем метод destroy()
всплывающего окна QuickObject и удаляем элемент из массива.
1
2
|
balloons[i].destroy();
balloons.splice(i, 1);
|
Шаг 29: Воспроизведение звука
Затем мы играем звук, указывающий на удар, усиливающий ощущение игры.
1
|
pop.play();
|
Шаг 30: Обновите счет и целевые счетчики
Счетчики очков и целей обновляются в соответствии с всплывающими подсказками и оставленными шариками.
1
2
|
scoreTF.text = String(int(scoreTF.text) + 50);
targetTF.text = String(balloons.length);
|
Шаг 31: Проверьте уровень завершен
Оповещение вызывается, когда все воздушные шары лопнут; мы увидим эту функцию позже в уроке.
1
2
3
4
|
if(targetTF.text == ‘0’)
{
alert();
}
|
Шаг 32: Начните зарядку
Этот код откроет указатель направления желудя, сбросит переменную y-impulse желудя и добавит прослушиватель энтерфрейма, который будет обрабатывать цель.
1
2
3
4
5
6
|
private final function startCharge(e:MouseEvent):void
{
yImpulse = 0;
gCircle.visible = true;
gCircle.addEventListener(Event.ENTER_FRAME, charge);
}
|
Шаг 33: Зарядка
Индикатор прицеливания поворачивается, чтобы показать направление, в котором будет выпущен желудь, и соответствующим образом корректирует переменную y-импульса. На направление выстрела влияют две переменные, xImpulse
и yImpulse
, которые позже объединяются, чтобы сформировать impulse
вектор. xImpulse
остается постоянным, а yImpulse
изменяется, когда пользователь удерживает нажатой кнопку мыши.
01
02
03
04
05
06
07
08
09
10
11
12
|
private final function charge(e:Event):void
{
gCircle.rotation -= 3;
yImpulse -= 0.2;
/* Prevent over-rotation */
if(gCircle.rotation < -80)
{
yImpulse = -5.4;
gCircle.rotation = -80;
}
}
|
Шаг 34: выстрел
Следующие действия происходят, когда кнопка мыши нажата.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
private final function shot(e:MouseEvent):void
{
/* Hide gCircle */
gCircle.removeEventListener(Event.ENTER_FRAME, charge);
gCircle.visible = false;
gCircle.rotation = 0;
/* Create new Acorn */
acorn = world.addBox({x:2.76, y:7.33, width: 0.66, height: 0.53, skin:Acorn, fixedRotation:true, draggable:false, density:1});
acorns.push(acorn);
/* Shoot acorn */
var impulse:b2Vec2 = new b2Vec2(xImpulse, yImpulse);
acorn.body.ApplyImpulse(impulse, acorn.body.GetWorldCenter());
/* Update Acorn counter */
acornsTF.text = String(int(acornsTF.text) -1);
}
|
Остановимся здесь, чтобы сделать быстрый тест и убедиться, что наш игровой код работает:
Имейте в виду, что некоторые строки были закомментированы, так как эти функции еще не созданы.
Шаг 35: функция обновления
Функция обновления выполнит серию операций EnterFrame. Давайте посмотрим эти действия в следующих шагах.
1
2
|
private final function update(e:Event):void
{
|
Шаг 36: Удалите желуди за кулисами
Следующие строки будут удалять все желуди, которые уходят со сцены.
1
2
3
4
5
6
7
8
|
/* Remove offstage acorns */
for(var i:int = 0; i < acorns.length; i++)
{
if(acorns[i].y > 10.66)
{
acorns[i].destroy();
acorns.splice(i, 1);
|
Шаг 37: Проверка уровня не пройдена
Игра заканчивается, когда у игрока заканчиваются желуди (или уничтожаются все воздушные шары, как упоминалось ранее).
1
2
3
4
5
6
7
8
9
|
/* Check for level failed */
if(int(acornsTF.text) <= 0)
{
alert(‘lose’);
}
}
}
}
|
Шаг 38: Перезагрузите уровень
Этот код запускается при нажатии кнопки «Перезагрузить». Это сбросит необходимые переменные и слушатели, чтобы перезапустить уровень.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
private final function restartLvl(e:MouseEvent):void
{
/* Remove Listeners */
gameListeners(‘rmv’);
/* Destroy World */
world = null;
/* Destroy Balloons, reset score and acorns */
for(var i:int = 0; i < balloons.length; i++)
{
balloons[i].destroy();
scoreTF.text = ‘0’;
acornsTF.text = ‘5’;
}
balloons = [];//clear balloons array
startGame();
}
|
Шаг 39: Оповещение
Эта функция остановит игру и покажет сообщение Game Over. Он также добавляет слушателя мыши для сброса игры при нажатии.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
private final function alert(gameState:String = ‘win’):void
{
gameListeners(‘rmv’);
world.stop();
var alert:AlertView = new AlertView();
alert.x = stage.stageWidth * 0.5;
alert.y = stage.stageHeight * 0.5;
alert.scoreTF.text = scoreTF.text;
alert.addEventListener(MouseEvent.MOUSE_UP, restart);
if(gameState == ‘lose’)
{
alert.titleTF.text = ‘Level Failed!’;
}
addChild(alert);
TweenNano.from(alert, 0.6, {scaleX: 0.2, scaleY: 0.2, ease:Expo.easeOut});
}
|
Шаг 40: перезагрузите
Этот код перезагрузит SWF, восстановив все значения и вернувшись к начальному экрану.
1
2
3
4
|
private final function restart(e:MouseEvent):void
{
navigateToURL(new URLRequest(stage.loaderInfo.url), ‘_level0’);
}
|
Вывод
Внесите свои собственные изменения в игру и наслаждайтесь ее созданием. Возможно, вы могли бы изменить расположение воздушных шаров, или добавить новые уровни, или изменить графику.
Надеюсь, вам понравился этот урок, спасибо за чтение!