Использование Phaser

Для Nano Dungeon мы будем использовать Phaser 3. В Интернете есть много материалов о Phaser, и при поиске в Интернете очень легко найти материалы о Phaser 2 вместо Phaser 3. Имейте в виду, что хотя обе библиотеки называются Phaser, API Phaser 2 и 3 не совпадают. Вы не сможете использовать код Phaser 2 с нашим проектом.

Phaser — очень гибкий фреймворк, вы можете использовать его для создания простых игрушек или сложных полнофункциональных игр. Это означает, что в Phaser есть много возможностей, которые мы не будем использовать в этой книге, поскольку они не применимы к нашей простой игре. Документация для Phaser носит всеобъемлющий характер. Не стесняйтесь проверить это, если вы хотите узнать больше о любом из API, показанных в этой книге.

Первая концепция, которую нам нужно понять — это сцены Phaser.

Сцены в Phaser

Игра Phaser организована по сценам. Каждая сцена содержит собственный игровой цикл, и некоторые игры достаточно просты, чтобы состоять из одной сцены. Вы можете думать о сценах как о состояниях, через которые проходит ваша игра. Типичная аркадная игра может иметь сцену для главного экрана, другую — для экрана параметров, сцену для игрового процесса и две сцены для конца игры: одну для победы, а другую для проигрыша. Когда игрок играет в игры, он органично проходит через эти сцены по мере необходимости. Большинство наших примеров будет с одной сценой.

Давайте создадим самую простую сцену и вместе проработаем код построчно. Код этого примера находится в папке chapter-2/example-1-simple-scene/ или его можно скачать здесь.

Простая сцена

Наш пример для этого раздела содержит файл HTML, файл JS и некоторые вспомогательные ресурсы для загрузки растрового шрифта. Используемый HTML довольно прост: его единственная функция — загрузить файл JS .

chapter-2/example-1-simple-scene/index.html:

<!DOCTYPE html>
<html>
<head>
    <title>Chapter 2 - Example 1 - Simple Scene</title>
    <script src="phaser.js"></script>
</head>

<body>
    <div id="game"></div>
    <script src="game.js"></script>
</body>

</html>

Основное внимание в этом примере будет уделено JS-файлу, который вставит нашу сцену Phaser в div#game, содержащуюся в этом HTML. Мы приведем здесь исходный код JS, а объясним его позже.

chapter-2/example-1-simple-scene/game.js:

const scene = {
    preload: function () {
        this.load.bitmapFont("arcade", "font/arcade.png", "font/arcade.xml");
    },
    create: function (){
        this.add.bitmapText(400, 300, "arcade", "Hello Phaser").setOrigin(0.5);
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: "#000",
    parent: "game",
    pixelArt: true,
    scene: scene,
    physics: {
        default: "arcade",
        arcade: {
            gravity: { y: 0 }
        }
    }
};

const game = new Phaser.Game(config);

Объект config

Чтобы запустить игру в Phaser нужен объект config, описывающий параметры, используемые для инициализации библиотеки. Эти параметры определены в объекте config в нашем примере. Есть некоторые очевидные свойства, такие как width, height и backgroundColor, которые легко понять. Остальные требуют дополнительных пояснений.

Свойство type сообщает Phaser, какой рендерер использовать. Есть два возможных рендера: это либо средство визуализации на основе canvas, либо средство визуализации на основе WebGL. WebGL лучше, но он поддерживается не во всех комбинациях браузера и устройств. Использование значение Phaser.AUTO позволяет Phaser выбрать лучший вариант для устройства, на котором он работает.

Свойство parent используется для указания того, какой HTML-элемент должен использоваться для хранения игры. В нашем случае мы указываем его на любой элемент c идентификатором game, который в нашем HTML является <DIV>.

Обычно Phaser использует некоторые процедуры сглаживания и антиалиасинга в графике, которую вы рисуете на экране, но мы отключаем их, установив для свойства pixelArt значение true, что сделает наш рогалик более старомодным и красивым.

Свойство physics немного сложнее. В Phaser входят различные физические движки, которые могут моделировать поведение вещей в реальном мире. Эти движки различаются по сложности и функциям, поэтому вы можете выбрать лучший вариант для своей игры. Это не тот двигатель, который используется для научного моделирования: то, что они предоставляют — это набор функций и механизмов, которые помогут вам реализовать физическую систему вашего игрового мира с точки зрения гравитации, ускорения пуль, столкновений и т. д. Это особенно полезно для аркад, в которых используются движущиеся и стреляющие объекты. Мы не используем это в этом примере, но все равно лучше это объяснить, потому что мы должны добавить данное свойство в объект config. В нашем примере это свойство имеет значение "arcade" (аркадный движок), который представляет собой самый простой физический движок, связанный с Phaser и устанавливающий гравитацию по оси Y к нолю, потому что мы делаем игру с видом сверху, и мы не хотим, чтобы что-то падало ниже игрового экрана, как если бы это было дно мира.

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

Объект scene

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

Сцена Phaser может быть построена с использованием объекта или класса, в этом примере мы используем объект. Жизненный цикл сцены проходит через разные состояния, и разработчик может реализовать только те состояния, которые имеют смысл для его сцены. Эти состояния представляют собой JS-функции, которые вызываются в синхронном потоке, так что каждый обратный вызов вызывается только после завершения предыдущего, как показано на рисунке 2-2 . Рисунок 2-2. Жизненный цикл сцены Phaser сначала вызывает функцию preload (предварительной загрузки), которая дает вам возможность предварительно загрузить любой внешний ресурс, который вам нужен. В нашем примере мы загружаем растровый шрифт. Эти шрифты используют изображение и XML-файл, поэтому мы передаем их оба в коде:

this.load.bitmapFont("arcade", "font/arcade.png", "font/arcade.xml");

В Phaser есть плагин загрузчика, с которым вы обычно взаимодействуете, используя this.load.*. В нашем случае мы используем загрузчик для шрифтов bitmapFonts и называем наш шрифт arcade. Это имя будет использоваться в последующем обратном вызове жизненного цикла.

После окончания работы preload Phaser вызовет функцию create. Эта функция обратного вызова используется для настройки вашей сцены в первый раз. Наш код для этого примера просто добавляет текст в центр экрана:

this.add.bitmapText(400, 300, "arcade", "Hello Phaser").setOrigin(0.5);

Подобно плагину загрузки, есть еще один плагин сцены — GameObjectFactory. Это причудливое название, из-за которого его сложнее понять, чем он есть на самом деле. Он упрощает добавление игровых объектов в сцену, вы обычно будете взаимодействовать с ним, используя this.add. *. В нашем примере мы добавляем bitmapText в координатах (400; 300) с текстом "Hello Phaser" с использованием шрифта arcade. Важная концепция, о которой мы должны поговорить подробнее, прежде чем перейти к последнему разделу кода, — это системы координат и то, что делает этот .setOrigin(0.5) в конце кода в create.

Phaser — это прежде всего двухмерный игровой движок, в котором мы рисуем объекты в прямоугольной декартовой системе координат на плоскости. Координаты начинаются с (0; 0), который является верхним левым углом холста, а значения увеличиваются вниз и вправо. Это может показаться нелогичным для математиков, но именно так работает большинство компьютерных графических движков (рис 2-3). Рисунок 2-3. Координаты и оси на сцене в Phaser.

Когда мы добавляем игровой объект на экран с помощью this.add.*, передаваемая нами координата закрепляется в верхнем левом углу нашего игрового объекта. Это означает, что если мы передадим координаты для середины экрана, добавляемый игровой объект будет иметь верхний левый угол в этой координате, а его тело будет немного ниже и правее.

Лучший способ расположить что-то по центру — это изменить способ привязки этих координат в данном игровом объекте, изменив его начало координат. Вы можете изменить положение координаты, которая считается исходной точкой для любого игрового объекта (воруг этой точки происходит трансформация, например вращение), используя метод setOrigin. Вы можете узнать больше об этом методе, прочитав его документацию. Здесь мы передаем ему единственный аргумент 0.5, который заставляет точку отсчета перемещаться на середину по осям x и y для этого игрового объекта. Таким образом, setOrigin(0.5) переносит начало координат объекта из верхнего левого угла к центру объекта, что значительно упрощает его размещение на экране в нужном нам месте.

Последняя строка кода инициализирует объект game и вызывает загрузку примера.

const game = new Phaser.Game(config);

Чтобы увидеть пример, вам нужно загрузить HTML с веб-сервера. Если вы выполнили шаги, описанные в начале этой главы, и установили live-server, вы можете использовать свой терминал, чтобы перейти в папку chapter-2/example-1-simple-scene/ и запустить live-server. Сервер запустится, а ваш браузер откроется по адресу: http://127.0.0.1:8080/. Вы должны увидеть пример, работающий следующим образом: Рисунок 2-4. Глава 2.Пример 1. Запуск в веб-браузере.

Этот пример не содержит всех методов жизненного цикла, показанных на рисунке 2-2, поддерживает только первые два метода preload и create, но в нем нет update, что означает, что сцена представляет собой статическую сцену, которая однажды создана и никогда не изменяется.