Для Nano Dungeon мы будем использовать Phaser 3. В Интернете есть много материалов о Phaser, и при поиске в Интернете очень легко найти материалы о Phaser 2 вместо Phaser 3. Имейте в виду, что хотя обе библиотеки называются Phaser, API Phaser 2 и 3 не совпадают. Вы не сможете использовать код Phaser 2 с нашим проектом.
Phaser — очень гибкий фреймворк, вы можете использовать его для создания простых игрушек или сложных полнофункциональных игр. Это означает, что в Phaser есть много возможностей, которые мы не будем использовать в этой книге, поскольку они не применимы к нашей простой игре. Документация для Phaser носит всеобъемлющий характер. Не стесняйтесь проверить это, если вы хотите узнать больше о любом из API, показанных в этой книге.
Первая концепция, которую нам нужно понять — это сцены 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);
Чтобы запустить игру в 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
, указывает на загружаемую сцену. Сцена является темой следующего раздела .
В этом примере используется очень простой объект сцены по сравнению с будущими примерами в этой книге. Тем не менее, это хорошая возможность для нас больше узнать о таких объектах, поскольку они будут наиболее часто используемой концепцией 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
, что означает, что сцена представляет собой статическую сцену, которая однажды создана и никогда не изменяется.