Статьи

Введение в FlashPunk: основы

Изучите основы работы FlashPunk — удивительной библиотеки, которая сэкономит ваше время и поможет создать идеальную игру!


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

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


FlashPunk логотип

FlashPunk — это библиотека ActionScript 3, созданная для разработки Flash-игр. По сути, он выполняет всю тяжелую работу за вас и позволяет полностью сосредоточиться на разработке игры, а не на движке, стоящем за ней. Самое приятное в этом то, что вам не нужен Flash Pro для работы с ним: вы можете делать все с помощью бесплатного редактора кода, такого как FlashDevelop . Не говоря уже о том, что это намного быстрее, когда дело доходит до рисования вещей на экране, так как он использует блиттинг!

В этом уроке будут рассмотрены все основы FlashPunk. После этого вы будете готовы сделать простую игру с этой удивительной библиотекой!


Начните с загрузки последней версии FlashPunk с официального сайта (в этом руководстве используется версия от 30 августа 2011 г.). Поместите папку «net» со всем ее содержимым в папку «src».

У FlashPunk есть класс Engine . Этот класс запускает все в библиотеке. Думайте об этом как о Main классе, но со специальным кодом для включения всех классов в FlashPunk. Чтобы использовать класс Engine , мы немного изменим класс Main .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
package
{
    import net.flashpunk.Engine;
     
    [Frame(factoryClass=»Preloader»)]
    public class Main extends Engine
    {
         
        public function Main():void
        {
             
        }
         
    }
 
}

Теперь наш класс расширяет Engine . В конструкторе Main нам нужно вызвать конструктор Engine : это то, что устанавливает важную информацию об игре: ширину, высоту, частоту кадров и должен ли двигатель работать с фиксированной частотой кадров или нет.

1
2
3
4
public function Main():void
{
    super(550, 400, 30, false);
}

Существует функция, которая может (и должна быть) переопределена из класса Engine : функция init() . Он будет запущен только один раз и инициализирует все, чтобы игра заработала.

1
2
3
4
override public function init():void
{
    trace(«The game has started!»);
}

Я уверен, что все хотят поместить что-то на экран и увидеть, как работает этот двигатель! Из-за этого следующие несколько шагов будут охватывать самые основы элементов FlashPunk, добавляя глубину по мере обучения.


В FlashPunk есть элементы под названием Worlds и Entities . Это основные элементы библиотеки, и вы будете работать с ними с самого начала и до самого конца вашей игры.

Миры очень похожи на то, что обычно называют «экраном». Все в вашей игре произойдет в мире: главное меню — это мир, который даст вам доступ к реальному игровому миру, где вы будете сражаться с некоторыми врагами и умрете, что приведет вас к игре по всему миру, с вашими счетами и Статистика о том, как хорошо вы сделали. Подробнее о мирах будет объяснено позже.

Сущности — это именно то, чем они кажутся; они живут в мире и что-то делают в нем: кнопка — это сущность; ваш персонаж — это сущность; враги и пули являются сущностями. Это вещи, которые дают жизнь игре.

Учитывая это, мы создадим игровой мир (у нас будет время сделать мир главного меню позже, давайте перейдем к некоторым действиям!), Расширив класс World FlashPunk:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
package
{
    import net.flashpunk.World;
     
    public class GameWorld extends World
    {
         
        public function GameWorld()
        {
             
        }
         
    }
 
}

Теперь, когда вы создали мир, вам нужно сказать FlashPunk, что вы хотите, чтобы этот мир был активным. Давайте сделаем это в Main.as :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
private var _gameWorld:GameWorld;
 
public function Main():void
{
    super(550, 400, 30, false);
     
    _gameWorld = new GameWorld();
}
 
override public function init():void
{
    trace(«The game has started!»);
     
    FP.world = _gameWorld;
}

И не забудьте импортировать net.flashpunk.FP !


Теперь, когда у нас есть наш мир, мы можем создать сущность, расширив класс Entity и добавив его в наш игровой мир:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
package
{
    import net.flashpunk.Entity;
     
    public class GameEntity extends Entity
    {
         
        public function GameEntity()
        {
             
        }
         
    }
 
}

И в GameWorld.as :

1
2
3
4
5
6
7
8
private var _gameEntity:GameEntity;
 
public function GameWorld()
{
    _gameEntity = new GameEntity();
     
    add(_gameEntity);
}

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

Мы добавим это маленькое изображение к нашей сущности:

Наша сущность

Графический объект может быть доступен с помощью graphic свойства. Вот как мы собираемся поместить изображение в него! Сначала вставьте это; затем просто передайте его конструктору Image , и FlashPunk позаботится о том, чтобы превратить его в нечто видимое для вас. Скомпилируйте и запустите сейчас. Сюрприз! Наша сущность там!

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
package
{
    import net.flashpunk.Entity;
    import net.flashpunk.graphics.Image;
     
    public class GameEntity extends Entity
    {
        [Embed(source = «/../img/EntityImage.png»)]
        private const IMAGE:Class;
         
        public function GameEntity()
        {
            graphic = new Image(IMAGE);
        }
         
    }
 
}

Вот что вы должны получить:

Сущность на экране

Теперь, когда у нас есть наш объект на экране, как насчет того, чтобы заставить его двигаться? У каждого Entity есть функция update() , которую вы должны переопределить, чтобы использовать. Эта функция вызывается каждым миром в начале каждого кадра. Если вам нужно заставить свою сущность двигаться, это место, где вы помещаете свой код!

1
2
3
4
5
override public function update():void
{
    x += 10 * FP.elapsed;
    y += 5 * FP.elapsed;
}

И не забудьте импортировать:

1
import net.flashpunk.FP;

Смотрите это в действии! (Обновите страницу, если вы ничего не видите здесь.)

Возможно, вы заметили использование FP.elapsed . FP.elapsed дает количество времени, прошедшее с последнего кадра (в секундах), что позволяет очень легко создавать основанное на времени движение. Однако, чтобы это работало, вы должны установить для четвертого параметра конструктора Engine значение false . Помните это (Шаг 2)? Установка его в false означает, что вы хотите, чтобы FlashPunk запускался с переменным временным шагом, тогда как установка в true заставляет FlashPunk работать с фиксированным временным шагом. В последнем случае вам не нужно использовать FP.elapsed . Вы будете знать, что каждый раз, когда вызывается функция update() , проходит кадр.


У нас есть сущность, движущаяся только в одном направлении на последнем шаге. Представляем ввод с клавиатуры: теперь вы сможете перемещать объект в нужное вам место!

У FlashPunk есть класс Input который заботится о вводе с клавиатуры и мыши. В этом уроке мы будем использовать только ввод с клавиатуры для движения. Это очень просто:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
override public function update():void
{
    if (Input.check(Key.A) || Input.check(Key.LEFT))
    {
        x -= 50 * FP.elapsed;
    }
    else if (Input.check(Key.D) || Input.check(Key.RIGHT))
    {
        x += 50 * FP.elapsed;
    }
     
    if (Input.check(Key.W) || Input.check(Key.UP))
    {
        y -= 50 * FP.elapsed;
    }
    else if (Input.check(Key.S) || Input.check(Key.DOWN))
    {
        y += 50 * FP.elapsed;
    }
}

И заявления на импорт:

1
2
import net.flashpunk.utils.Input;
import net.flashpunk.utils.Key;

Input.check() возвращает true если Key переданная в качестве аргумента, нажата во время Input.check() функции. Существуют и другие очень полезные функции, такие как Input.pressed() , которая возвращает true если клавиша была нажата во время Input.pressed() функции (т. Input.pressed() Клавиша была вверху кадра назад и теперь не работает), или Input.released() , что делает с точностью до наоборот.

Еще одна интересная вещь, которую позволяет делать класс Input , — это определение множества ключей под одним именем. Например, мы можем определить Key.UP , Key.W и Key.I как "UP" и проверять только Input.check("UP") . Таким образом, мы можем улучшить нашу функцию:

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
public function GameEntity()
{
    graphic = new Image(IMAGE);
     
    Input.define(«UP», Key.W, Key.UP);
    Input.define(«DOWN», Key.S, Key.DOWN);
    Input.define(«LEFT», Key.A, Key.LEFT);
    Input.define(«RIGHT», Key.D, Key.RIGHT);
}
 
override public function update():void
{
    if (Input.check(«LEFT»))
    {
        x -= 50 * FP.elapsed;
    }
    else if (Input.check(«RIGHT»))
    {
        x += 50 * FP.elapsed;
    }
     
    if (Input.check(«UP»))
    {
        y -= 50 * FP.elapsed;
    }
    else if (Input.check(«DOWN»))
    {
        y += 50 * FP.elapsed;
    }
}

И вот что вы должны получить:


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

У сущностей есть свойство с именем type . Вы можете установить это свойство для любой строки, которую вы хотите. Это позволяет вам объединять ваши сущности в группы, что очень полезно на следующем этапе (о мирах). Мы можем, например, установить тип нашей сущности на «GameEntity»:

01
02
03
04
05
06
07
08
09
10
11
public function GameEntity()
{
    graphic = new Image(IMAGE);
     
    Input.define(«UP», Key.W, Key.UP);
    Input.define(«DOWN», Key.S, Key.DOWN);
    Input.define(«LEFT», Key.A, Key.LEFT);
    Input.define(«RIGHT», Key.D, Key.RIGHT);
     
    type = «GameEntity»;
}

Исходя из этого, у нас есть полезное свойство world а также функции added() и removed() . Свойство world позволяет вам получить доступ к миру из кода объекта, как только объект был добавлен в мир. Это как свойство stage в обычной разработке Flash; функции похожи на REMOVED_FROM_STAGE событий ADDED_TO_STAGE и REMOVED_FROM_STAGE . Вот пример функций, работающих в GameEntity.as :

01
02
03
04
05
06
07
08
09
10
11
override public function added():void
{
    trace(«The entity has been added to the world!»);
     
    trace(«Entities in the world: » + world.count);
}
 
override public function removed():void
{
    trace(«The entity has been removed from the world!»);
}

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

Миры имеют функции update() же, как и сущности, но их функция немного отличается: в классе World есть реальный код. Это означает, что вам придется вызывать super.update() каждый раз, когда вы переопределяете эту функцию.

Помимо сущностей, в миры также может быть добавлена графика . Графика — это изображения, которые вам не нужно обновлять (FlashPunk по-прежнему создает сущность, чтобы добавить их в мир, поэтому движок все равно будет отправлять вызов функции update() ). Вы можете добавить их, вызвав addGraphic() .

Самое важное в мирах — это то, что у них есть несколько функций для извлечения определенных сущностей: getType() , getClass() , getAll() , getLayer() и getInstance() . Таким образом, вы можете сделать так, чтобы мир возвратил массив всех пуль, находящихся в данный момент в игре, чтобы вы могли проверить их на предмет столкновения. Очень удобно, должен сказать!

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

Наша вторая сущность
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
[Embed(source = «/../img/EntityImage2.png»)]
private const IMAGE:Class;
 
public function GameWorld()
{
    _gameEntity = new GameEntity();
     
    add(_gameEntity);
     
    addGraphic(new Image(IMAGE), 0, 50, 50);
}
 
override public function update():void
{
    super.update();
     
    var entityArray:Array = [];
     
    getType(«GameEntity», entityArray);
     
    for each (var entity:Entity in entityArray)
    {
        entity.x = entity.x > 550 ?
        entity.y = entity.y > 400 ?
    }
}

И не забудьте импортировать net.flashpunk.graphics.Image !

В этом коде addGraphic() функции addGraphic() добавляет еще один рисунок, похожий на _gameEntity — думайте о нем как о NPC! — миру в позиции (50, 50). Строки 23-31 показывают пример получения только сущностей определенного вида: мы вызываем getType() чтобы получить только сущности типа «GameEntity» (в настоящее время только одна сущность). После этого мы перебираем каждую найденную сущность и не даем им пройти правую и нижнюю границу. (Таким образом, сущность может выйти за пределы экрана, но не далеко.) Просто, не так ли?


Время для чего-то более интересного! FlashPunk поддерживает анимацию всех видов. Все, что вам нужно сделать, это вместо создания экземпляра Image создать экземпляр Spritemap . Этот класс получает таблицу спрайтов и позволяет отображать кадры и ссылаться на анимацию.

В классе нашей сущности, вставьте эту карту спрайта:

Лист нашей сущности

Затем создайте экземпляр Spritemap и передайте spritesheet в качестве параметра конструктору. После этого все дело в вызове функций add() и play() !

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
[Embed(source = «/../img/EntitySheet.png»)]
private const SHEET:Class;
 
private var _timeInterval:Number;
 
public function GameEntity()
{
    graphic = new Spritemap(SHEET, 40, 20, onAnimationEnd);
    Spritemap(graphic).add(«Stopped», [0]);
    Spritemap(graphic).add(«Blinking», [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 24);
     
    Input.define(«UP», Key.W, Key.UP);
    Input.define(«DOWN», Key.S, Key.DOWN);
    Input.define(«LEFT», Key.A, Key.LEFT);
    Input.define(«RIGHT», Key.D, Key.RIGHT);
     
    type = «GameEntity»;
     
    Spritemap(graphic).play(«Blinking»);
}
 
private function onAnimationEnd():void
{
    Spritemap(graphic).play(«Stopped»);
     
    _timeInterval = 0;
}
 
override public function update():void
{
    _timeInterval += FP.elapsed;
     
    if (_timeInterval >= 3)
    {
        Spritemap(graphic).play(«Blinking»);
    }
     
    if (Input.check(«LEFT»))
    {
        x -= 50 * FP.elapsed;
    }
    else if (Input.check(«RIGHT»))
    {
        x += 50 * FP.elapsed;
    }
     
    if (Input.check(«UP»))
    {
        y -= 50 * FP.elapsed;
    }
    else if (Input.check(«DOWN»))
    {
        y += 50 * FP.elapsed;
    }
}

Конструктор Spritemap (строка 19) принимает четыре аргумента: источник для получения графики, ширину и высоту каждого кадра таблицы спрайтов и функцию обратного вызова, вызываемую по окончании анимации (необязательно). В конструкторе GameEntity мы создаем Spritemap и определяем две анимации: «Остановлено», которое содержит только первый кадр и работает со скоростью 0 кадров в секунду (остановлено!), И «Мигает», которое содержит все кадры и работает со скоростью 24 кадра в секунду. ,

Остальная часть кода предназначена для воспроизведения анимации «Мигающий» каждые три секунды.

Посмотрите на мигание нашей сущности:


Когда все работает хорошо, пришло время представить еще одну функцию: обнаружение столкновений. FlashPunk имеет отличную систему обнаружения столкновений: все, что нам нужно сделать, это установить хитбоксы для наших сущностей и попросить мир проверить наличие столкновений. Для этого мы создадим еще одну сущность с именем Box которая будет содержать следующую графику:

Изображение коробки
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
package
{
    import net.flashpunk.Entity;
    import net.flashpunk.graphics.Image;
     
    public class Box extends Entity
    {
        [Embed(source = «/../img/BoxImage.png»)]
        private const IMAGE:Class;
         
        public function Box()
        {
            graphic = new Image(IMAGE);
             
            setHitbox(60, 60);
        }
         
    }
 
}

И внутри GameWorld.as :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
private var _box:Box;
 
public function GameWorld()
{
    _gameEntity = new GameEntity();
    _box = new Box();
     
    add(_gameEntity);
    add(_box);
     
    _box.x = 200;
    _box.y = 150;
     
    addGraphic(new Image(IMAGE), 0, 50, 50);
}

Функция setHitbox() устанавливает прямоугольник, который будет действовать как поле попадания для сущности. Первые два параметра — это ширина и высота поля. Следующие два параметра (необязательные) являются исходными координатами (x и y) прямоугольника. Делаем то же самое для GameEntity :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
public function GameEntity()
{
    graphic = new Spritemap(SHEET, 40, 20, onAnimationEnd);
    Spritemap(graphic).add(«Stopped», [0]);
    Spritemap(graphic).add(«Blinking», [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 24);
     
    Input.define(«UP», Key.W, Key.UP);
    Input.define(«DOWN», Key.S, Key.DOWN);
    Input.define(«LEFT», Key.A, Key.LEFT);
    Input.define(«RIGHT», Key.D, Key.RIGHT);
     
    type = «GameEntity»;
     
    Spritemap(graphic).play(«Blinking»);
     
    setHitbox(40, 20);
}

Теперь, когда у нас есть и наша сущность, и ящик с хитбоксами, нам нужно проверить наличие коллизий в мировом классе:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
override public function update():void
{
    super.update();
     
    var entityArray:Array = [];
     
    getType(«GameEntity», entityArray);
     
    for each (var entity:Entity in entityArray)
    {
        entity.x = entity.x > 550 ?
        entity.y = entity.y > 400 ?
    }
     
    if (_gameEntity.collideWith(_box, _gameEntity.x, _gameEntity.y))
    {
        trace(«Collision!»);
    }
}

Функция collideWith() проверяет столкновение с сущностью, переданной в качестве аргумента, фактически помещая первую сущность (в данном случае _gameEntity ) в позицию, указанную вторым и третьим аргументами.

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
override public function update():void
{
    super.update();
     
    var entityArray:Array = [];
     
    getType(«GameEntity», entityArray);
     
    for each (var entity:Entity in entityArray)
    {
        entity.x = entity.x > 550 ?
        entity.y = entity.y > 400 ?
    }
     
    if (_gameEntity.collideWith(_box, _gameEntity.x, _gameEntity.y))
    {
        _gameEntity.x = _gameEntity.y = 0;
    }
}

Посмотрите на пример. Попробуйте переместить сущность в коробку.


FlashPunk по умолчанию не имеет кнопок. Почти во всех играх нужны кнопки, поэтому на этом шаге мы создадим класс Button . Прежде всего, кнопка имеет три состояния (как вы, наверное, знаете из обычной разработки Flash): «Вверх», «За» и «Вниз». Эта таблица показывает, что:

Кнопка

А теперь давайте начнем класс:

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
35
package
{
    import net.flashpunk.Entity;
    import net.flashpunk.graphics.Spritemap;
     
    public class Button extends Entity
    {
        protected var _map:Spritemap;
         
        public function Button(x:Number = 0, y:Number = 0)
        {
            super(x, y);
        }
         
        public function setSpritemap(asset:*, frameW:uint, frameH:uint):void
        {
            _map = new Spritemap(asset, frameW, frameH);
             
            _map.add(«Up», [0]);
            _map.add(«Over», [1]);
            _map.add(«Down», [2]);
             
            graphic = _map;
             
            setHitbox(frameW, frameH);
        }
         
        override public function render():void
        {
            super.render();
        }
         
    }
 
}

Функция setSpritemap() устанавливает spritemap для кнопки и устанавливает «анимацию» для кнопки. Всегда изображение должно иметь сначала рамку «вверх», затем «сверху», а затем рамку «вниз». Также есть вызов setHitbox() . Хитбокс будет использоваться для проверки, находится ли мышь над рамкой кнопки.


Теперь, когда у нас есть кнопка, успешно показывающая изображение, пришло время создавать элементы управления вверх, вниз и вниз. Мы сделаем это, создав два логических атрибута: «over» и «clicked». Мы также определим, находится ли мышь над хит-боксом кнопки или нет. Добавьте эти функции в Button.as :

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
protected var _over:Boolean;
protected var _clicked:Boolean;
 
override public function update():void
{
    if (!world)
    {
        return;
    }
     
    _over = false;
    _clicked = false;
     
    if (collidePoint(x — world.camera.x, y — world.camera.y, Input.mouseX, Input.mouseY))
    {
        if (Input.mouseDown)
        {
            mouseDown();
        }
        else
        {
            mouseOver();
        }
    }
}
 
protected function mouseOver():void
{
    _over = true;
}
 
protected function mouseDown():void
{
    _clicked = true;
}
 
override public function render():void
{
    if (_clicked)
    {
        _map.play(«Down»);
    }
    else if (_over)
    {
        _map.play(«Over»);
    }
    else
    {
        _map.play(«Up»);
    }
     
    super.render();
}

И не забудьте импортировать net.flashpunk.utils.Input .

Следуя логике в update() : во-первых, оба атрибута ( _clicked и _over ) установлены в false. После этого мы проверяем, находится ли мышь над кнопкой. Если это не так, атрибуты останутся ложными, и кнопка будет в состоянии «Вверх». Если мышь нажата, мы проверяем, нажата ли кнопка мыши. Если это правда, кнопка находится в состоянии «Вниз» и _clicked установлен в true; если значение равно false, кнопка находится в состоянии «Over», а для атрибута _over установлено значение true. Эти атрибуты будут определять, к какому фрейму должна идти spritemap.

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

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
protected var _callback:Function;
protected var _argument:*;
 
public function Button(callback:Function, argument:*, x:Number = 0, y:Number = 0)
{
    super(x, y);
     
    _callback = callback;
    _argument = argument;
}
 
override public function update():void
{
    if (!world)
    {
        return;
    }
     
    _over = false;
    _clicked = false;
     
    if (collidePoint(x — world.camera.x, y — world.camera.y, Input.mouseX, Input.mouseY))
    {
        if (Input.mouseReleased)
        {
            clicked();
        }
        else if (Input.mouseDown)
        {
            mouseDown();
        }
        else
        {
            mouseOver();
        }
    }
}
 
protected function clicked():void
{
    if (!_argument)
    {
        _callback();
    }
    else
    {
        _callback(_argument);
    }
}

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


Множество шагов и ничего на экране … Время, чтобы вставить туда кнопку! Это так же просто, как добавить этот код в GameWorld.as :

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
[Embed(source = «/../img/ButtonSheet.png»)]
private const BUTTONSHEET:Class;
 
private var _button:Button;
 
public function GameWorld()
{
    _gameEntity = new GameEntity();
    _box = new Box();
    _button = new Button(onButtonClick, null);
     
    _button.setSpritemap(BUTTONSHEET, 50, 40);
     
    add(_gameEntity);
    add(_box);
    add(_button);
     
    _box.x = 200;
    _box.y = 150;
     
    _button.x = 400;
    _button.y = 200;
     
    addGraphic(new Image(IMAGE), 0, 50, 50);
}
 
private function onButtonClick():void
{
    FP.screen.color = Math.random() * 0xFFFFFF;
     
    trace(«The button has been clicked!»);
}

Теперь все, что вам нужно сделать, это скомпилировать проект, и кнопка будет там!


А теперь последняя функция от FlashPunk, которая будет представлена ​​в этом уроке! Console — это инструмент для отладки FlashPunk: в нем есть логи, которые во многом похожи на следы; показывает время, необходимое для запуска важного шага двигателя; и отображает, сколько объектов на экране и текущий FPS. Это отличный инструмент для разработки вашей игры. Чтобы включить его, просто добавьте следующую строку в Main.as :

1
2
3
4
5
6
7
8
override public function init():void
{
    trace(«The game has started!»);
     
    FP.console.enable();
     
    FP.world = _gameWorld;
}

И для записи чего-либо в нем используйте FP.log() . Например, давайте изменим этот вызов trace() :

1
2
3
4
5
6
7
8
override public function init():void
{
    FP.console.enable();
     
    FP.log(«The game has started!»);
     
    FP.world = _gameWorld;
}

Вот и все! Вы увидите, что часть «Вывод» из консоли отладки теперь показывает журнал. Вы можете изменить все вызовы trace() в нашем коде на вызовы FP.log() .


И это наше введение в FlashPunk, охватывающее самые важные аспекты этой удивительной библиотеки: сущности, миры, изображения и анимации; столкновение, кнопки, ввод и движение. Надеюсь, вам понравится эта библиотека так же, как и мне — она ​​действительно облегчает работу!