Статьи

Дизайн и разработка фантастической игры Flash Shooting Gallery

В этом уроке Premium мы узнаем, как объединить несколько классов ActionScript 3 и навыки для создания фантастической игры в тире.


Используя Flash Tools, мы создадим красивую графику, которая будет работать на нескольких классах ActionScript 3, таких как MouseCursor, Tween Nano, Sprite, Timers и другие события.

Пользователь сможет ввести имя игрока и уничтожить заранее определенное количество дартс до окончания игры.


Откройте Flash и создайте документ шириной 720 пикселей и высотой 480 пикселей. Установите частоту кадров 24 к / с.




Красочный и приятный на ощупь интерфейс будет питать наш код, он включает в себя несколько фигур, кнопок, пользовательских курсоров и многое другое

Перейдите к следующим шагам, чтобы узнать, как создать этот графический интерфейс.



Голубой радиальный градиент будет небом.

Выберите инструмент Rectangle Tool (R) и создайте прямоугольник 720×335 px, используйте панель цветов, чтобы применить радиальный фон #EFFDFE, # 7FD7FF.


Три основные фигуры будут использоваться для облаков, остальные будут дублированы MovieClips.


Используйте инструмент Oval Tool (O) для создания кругов и овалов разных размеров, после того, как вы получили понравившуюся форму облака, раскрасьте их, используя градиентную заливку # F1FBFF, # C3ECFF. Используйте Gradient Transform Tool (F), чтобы вращать градиент.




Давайте добавим немного гор на сцену.

Используйте Rectangle Tool, чтобы создать два прямоугольника по всей сцене, используйте этот градиент на них # 8DB400, # CFF500.


С помощью инструмента «Выделение» (V) возьмите углы прямоугольника и придайте им менее квадратную форму.


Используйте ту же технику, только на этот раз перетаскивая из сторон прямоугольников (вы увидите кривую в курсоре мыши), используйте инструмент Преобразование градиента, чтобы вращать градиент.



Это трава, которую мы будем создавать. Это сделано из трех или четырех различных форм в разных цветах.


Используйте инструмент «Прямоугольник», чтобы создать прямоугольник, и используйте технику гор, чтобы начать модификацию фигуры. Вы можете увидеть, как трава была создана, глядя на следующее изображение:


Как только у вас появится первая форма травы, вам просто нужно изменить цвета и размеры, а затем соединить их, и все готово.



Графика на земле довольно проста, # 5F4123 цветной фон, с некоторыми камнями # 3A2814.


Ваш фон должен выглядеть следующим образом:



Информационная панель покажет имя игрока, а также текущий счет. Давайте начнем с создания фона.

Используйте Rectangle Primitive Tool, чтобы создать 230×40 px, #CCCCCC, 60% альфа-прямоугольник и разместите его, как показано на изображении.


Дублируйте форму и измените ее на 225x30px, # 000000, альфа 70%. Центрируйте новую фигуру на сером фоне.


Преобразуйте новую форму в MovieClip и назовите ее infoBg .

Используйте Text Tool (T), чтобы создать два динамических текстовых поля и поместить их на задний план.


Этот формат используется для имени игрока: Walway Rounded, 28pt, # 6CA8E6, имя экземпляра: playerName .

Текстовое поле сбоку: округленный проход, 32 пт, #FFFFFF, имя экземпляра: счет .


Пользовательский курсор состоит из серии скругленных прямоугольников и круга.


Посмотрите на следующее изображение, чтобы лучше понять, как оно было сделано.



Дартс является одним из основных элементов в игре, он является целью уничтожить.

Используйте инструмент «Овал», чтобы создать круг размером 80×80 px с этим линейным градиентом # 697368, # 060604.


Дублируйте форму, измените ее размер до 64×64 px и измените градиент на # F6F6F6, #DDDDDD.


Используйте инструмент «Овальный примитив», чтобы создать круг размером 46×46 пикселей и изменить внутренний радиус до 75,00. Используйте снова черный градиент.


Дублируйте белый круг, измените его размер до 18×18 пикселей и заполните его # AF4F50.


Преобразуйте Shapes в MovieClip и назовите его Dartboard , обязательно установите флажок « Экспорт для ActionScript» .


Счетчик попаданий будет в левом верхнем углу сцены.


Используйте тот же формат текстового поля playerName, просто измените цвет на # FEE75C. Динамическое текстовое поле называется хитами .



Это название панели, ничего сложного в этом нет.

Это будет первым, что показано игроку. Он содержит поле ввода TextField с именем nameField и дартс, используемые в качестве кнопки с именем beginButton.


Мы сыграем звук, когда дротик ударит. Есть много сайтов, где вы можете скачать звуковые эффекты и музыку онлайн, вы можете получить эффект, используемый в руководстве здесь .


Чтобы использовать звук, нам сначала нужно импортировать его в библиотеку. Нажмите Cmd + R, найдите загруженный звук и нажмите «Открыть».


Откройте библиотеку и щелкните правой кнопкой мыши значок звука, выберите « Свойства» и отметьте поле « Экспорт для ActionScript» .


На этом графическая фаза заканчивается, пусть начинается ActionScripting!


Создайте новый (Cmd + N) класс ActionScript 3.0 и сохраните его как Main.as в папке вашего класса.




Мы будем использовать другой движок анимации движения, отличающийся от встроенного во флэш-память по умолчанию, это повысит производительность (также проще в использовании). Вы можете скачать Tween Nano с официального сайта .


Ключевое слово package позволяет вам организовать ваш код в группы, которые могут быть импортированы другими скриптами. Рекомендуется называть их, начиная с буквы нижнего регистра, и использовать межстрочные буквы для следующих слов, например: myClasses . Также принято называть их, используя сайт вашей компании: com.mycompany.classesType.myClass .

В этом примере мы используем один класс, поэтому на самом деле нет необходимости создавать папку классов.

1
2
package
{

Это классы, которые нам нужно импортировать, чтобы наш класс работал, директива import делает внешние классы и пакеты доступными для вашего кода.

1
2
3
4
5
6
7
import flash.display.Sprite;
import flash.ui.Mouse;
import com.greensock.TweenNano;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;

Здесь мы объявляем класс с помощью ключевого слова определения класса, за которым следует имя, которое мы хотим для класса, помните, что вы должны сохранить файл под этим именем.

Ключевое слово extends определяет класс, который является подклассом другого класса. Подкласс наследует все методы, свойства и функции, так что мы можем использовать их в нашем классе.

1
2
public class Main extends Sprite
{

Это переменные, которые мы будем использовать, прочитайте комментарии в коде, чтобы узнать больше о каждой из них.

01
02
03
04
05
06
07
08
09
10
private var gridY:Array = new Array();
private var gridX:Array = new Array();//Stores the x coordinate in which a dartboard can be positioned
private var xPos:int = 0;
private var yPos:int = 0;//The latest y position used by a dartboard
private var dartboards:Array = new Array();
private var smack:SmackSound = new SmackSound();
private var timer:Timer = new Timer(3000);
private var currentDartboards:int = 0;
private var levelComplete:int = 30;
private var scorePanel:ScorePanel = new ScorePanel();

Конструктор — это функция, которая запускается, когда объект создается из класса, этот код выполняется первым, когда вы создаете экземпляр объекта или запускается с использованием класса документа.

Вызывает необходимые функции для запуска игры. Проверьте эти функции в следующих шагах.

1
2
3
4
5
6
7
public function Main():void
{
    startCustomCursor();
    namePanelHandler();
    updateScore();
    bg.addEventListener(MouseEvent.MOUSE_DOWN, addHits);
}

Эта функция анимирует панель имен на сцене и добавляет слушателя к кнопке, чтобы установить имя в текстовом поле при активации.

1
2
3
4
5
6
private function namePanelHandler():void
{
    namePanel.beginButton.stop();
    namePanel.beginButton.addEventListener(MouseEvent.MOUSE_UP, setPlayerName);
    TweenNano.from(namePanel, 0.5, {y: -namePanel.height/2});
}

Устанавливает имя, записанное в текстовом поле «Панель имени», в поле playerName на панели «Информация».

1
2
3
4
5
6
7
private function setPlayerName(e:MouseEvent):void
{
    smack.play();
    namePanel.beginButton.gotoAndPlay(3);
    playerName.text = namePanel.nameField.text;
    TweenNano.to(namePanel, 0.5, {y: stage.stageHeight + namePanel.height/2, onComplete: beginGame});
}

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

1
2
3
4
5
private function startCustomCursor():void
{
    Mouse.hide();
    cursor.startDrag(true);
}

Это важная функция, она вычисляет площадь сцены и создает сетку на основе размера Дартс (80 пикселей).

Мы будем использовать полученные массивы позже, чтобы избежать появления дротиков перед собой.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
private function calculateGrid():void
{
    gridX = [];
    gridY = [];
  
    for (var h:int = 1; h <= (stage.stageHeight — 160) / 80; h++) //The — reduces invisible/used area
    {
        gridY.push(80 * h);
    }
  
    for (var v:int = 1; v <= (stage.stageWidth — 160) / 80; v++)
    {
        gridX.push(80 * v);
    }
}

Следующая функция создаст и добавит мишени, установленные параметром количества .

Из этой логики следует:

  • Рассчитать сетку (он делает это только один раз)
  • Создайте новый экземпляр Dartboard и не позволяйте ему играть
  • Используйте случайную позицию из массивов позиций
  • Удалить последнюю позицию, используемую, чтобы избежать добавления дартс в том же месте
  • Добавьте слушателя уничтожения в дартс
  • Добавить дротик на сцену и анимировать его
  • Добавить дартс в массив дартс
  • Получите следующую наибольшую глубину (часто запрашиваемую в AS3, обратите внимание) для пользовательского курсора
  • Добавьте один в показанный список дартс
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private function addRandomDartboards(amount:int):void
{
    calculateGrid();
  
    for (var i:int = 0; i < amount; i++)
    {
        var dartboard:Dartboard = new Dartboard();
  
        dartboard.stop();
  
        xPos = gridX[Math.floor(Math.random() * gridX.length)];
        yPos = gridY[Math.floor(Math.random() * gridY.length)];
  
        dartboard.x = xPos + 40;
        dartboard.y = yPos + 40;
  
        gridX.splice(gridX.indexOf(xPos), 1);
        gridY.splice(gridY.indexOf(yPos), 1);
  
        dartboard.addEventListener(MouseEvent.MOUSE_DOWN, destroyDartboard);
  
        addChild(dartboard);
  
        TweenNano.from(dartboard, 0.6, {rotationY: 180});
        TweenNano.from(dartboard, 0.6, {scaleX: 0.4});
        TweenNano.from(dartboard, 0.6, {scaleY: 0.4});
  
        dartboards.push(dartboard);
  
        setChildIndex(cursor, (numChildren — 1));
  
        currentDartboards++;
    }
}

Эта функция обрабатывает анимацию для пораженной мишени, она также удаляет мишень из массива мишеней и добавляет новые, если на сцене больше нет клипов.

Множество анимаций и баллов здесь также обрабатываются.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
private function destroyDartboard(e:MouseEvent):void
{
    smack.play();
    e.target.removeEventListener(MouseEvent.MOUSE_DOWN, destroyDartboard);
    e.target.gotoAndPlay(3);
    e.target.addEventListener(Event.ENTER_FRAME, removeDartboard);
  
    dartboards.splice(dartboards.indexOf(e.target), 1);
  
    if (dartboards.length == 0) //Add new darboards if all have been destroyed
    {
        timer.stop();
        addRandomDartboards(5);
        timer.start();
    }
  
    /*Update scores, hits and play hit animation*/
  
    updateScore(1);
    updateHits(1);
  
    var plusOne:ScorePlus = new ScorePlus();
  
    plusOne.x = e.target.x;
    plusOne.y = e.target.y + plusOne.height;
  
    addChild(plusOne);
  
    TweenNano.from(plusOne, 0.5, {scaleX: 0.5});
    TweenNano.from(plusOne, 0.5, {scaleY: 0.5, onComplete:removeScoreGFX, onCompleteParams: [plusOne]});
}

Удаляет фильм «+1».

1
2
3
4
private function removeScoreGFX(target:Sprite):void
{
    removeChild(target);
}

Проверяет, закончилась ли анимация дарла, и удаляет ее, если это правда.

1
2
3
4
5
6
7
8
private function removeDartboard(e:Event):void
{
    if (e.target.currentFrame == 8)
    {
        e.target.removeEventListener(Event.ENTER_FRAME, removeDartboard);
        removeChild(e.target as Sprite);
    }
}

Добавляет указанный счет в счет TextField.

1
2
3
4
private function updateScore(addToScore:int = 0):void
{
    score.text = String(int(score.text) + addToScore);
}

Добавляет 1 к количеству попаданий, это вызывается, когда дротик уничтожен.

1
2
3
4
5
private function updateHits(addToHits:int = 0):void
{
    hits.text = String(int(hits.text) + addToHits);
    TweenNano.from(hits, 0.3, {y: -5});
}

Добавляет общий счет попадания в счет TextField.

1
2
3
4
5
private function addHits(e:MouseEvent):void
{
    score.text = String(int(score.text) + int(hits.text));
    hits.text = «0»;
}

Инициирует игру.

Создает дартс, удаляет панель с именами игроков и запускает таймер.

01
02
03
04
05
06
07
08
09
10
11
private function beginGame(restarting:Boolean = false):void
{
    if (! restarting)
    {
        removeChild(namePanel);
    }
  
    addRandomDartboards(5);
    timer.addEventListener(TimerEvent.TIMER, removeRemainingListeners);
    timer.start();
}

Удаляет дротики, которые не были поражены, и добавляет новые, если уровень не завершен.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
private function removeRemaining():void
{
    for (var i:int = dartboards.length-1; i >= 0; i—)
    {
        removeChild(dartboards[i]);
        dartboards.length = i;
  
        if (dartboards.length == 0 && currentDartboards < levelComplete)
        {
            addRandomDartboards(5);
            timer.start();
        }
        else if (dartboards.length == 0 && currentDartboards >= levelComplete) //If level complete
        {
            levelCompleted();
        }
    }
}

Если все разрешенные мишени были отображены на сцене, эта функция будет выполнена.

Он рассчитывает окончательный счет, скрывает информационную панель и показывает ScorePanel.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
private function levelCompleted():void
{
    score.text = String(int(score.text) + int(hits.text));
    hits.text = «0»;
  
    score.visible = false;
    playerName.visible = false;
  
    TweenNano.to(infoBg, 0.5, {x: -infoBg.width/2});
  
    scorePanel.x = stage.stageWidth + scorePanel.width / 2;
    scorePanel.y = stage.stageHeight / 2;
  
    scorePanel.myScore.text = score.text;
    scorePanel.playAgain.addEventListener(MouseEvent.MOUSE_UP, restart);
  
    addChild(scorePanel);
  
    setChildIndex(cursor, (numChildren — 1));
  
    TweenNano.to(scorePanel, 0.5, {x: stage.stageWidth/2});
}

Следующие строки делают возможным перезапуск. Вы найдете все объясненное в комментариях.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
private function restart(e:MouseEvent):void
{
    score.visible = true;
    score.text = «0»;
    playerName.visible = true;
  
    scorePanel.playAgain.removeEventListener(MouseEvent.MOUSE_UP, restart);
  
    TweenNano.to(infoBg, 0.5, {x: infoBg.width/2});
    TweenNano.to(scorePanel, 0.5, {x: stage.stageWidth + scorePanel.width/2, onComplete: removeScorePanel});
  
    currentDartboards = 0;
    beginGame(true);
}

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

1
2
3
4
private function removeScorePanel():void
{
    removeChild(scorePanel);
}


Мы будем использовать класс документа в этом руководстве, если вы не знаете, как его использовать или немного запутались, прочитайте эту подсказку .



Теперь вы готовы протестировать свою игру !, зайдите во Flash и нажмите Cmd + Return, убедитесь, что все работает как положено, и получайте удовольствие!


Конечный результат — красочная и интересная игра, попробуйте настроить ее, а как насчет порта для Android?

Надеюсь, вам понравился этот урок, спасибо за чтение!