О чем этот пример
Phaser 3 предлагает несколько способов объявления сцен — ключевых контейнеров для игровой логики. Использование синтаксиса класса, унаследованного от `Phaser.Scene`, — это проверенный временем подход, знакомый разработчикам с опытом в объектно-ориентированном программировании. Он обеспечивает чёткую структуру, явное наследование и полный контроль над жизненным циклом сцены, что особенно полезно для поддержки и масштабирования крупных проектов.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
const MyScene = new Phaser.Class({
Extends: Phaser.Scene,
initialize:
function MyScene (config)
{
Phaser.Scene.call(this, config)
},
preload: function ()
{
this.load.image('face', 'assets/pics/bw-face.png');
},
create: function ()
{
this.face = this.add.image(400, 300, 'face');
}
});
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
backgroundColor: '#000000',
parent: 'phaser-example',
scene: MyScene
};
const game = new Phaser.Game(config);
Создание класса сцены
В этом подходе мы не используем ключевое слово class из ES6, а полагаемся на внутреннюю систему классов Phaser — Phaser.Class. Это позволяет создавать конструкторы сцен с явным указанием наследования.
Сначала мы определяем новый класс MyScene. Ключевой момент — указание, что он расширяет (наследует) базовый класс Phaser.Scene. Это даёт нашей сцене доступ ко всем методам движка, таким как preload, create и update.
const MyScene = new Phaser.Class({
Extends: Phaser.Scene,
Далее идёт функция initialize, которая выступает в роли конструктора. Здесь мы вызываем конструктор родительского класса (Phaser.Scene), передавая ему конфигурацию.
initialize:
function MyScene (config)
{
Phaser.Scene.call(this, config);
},
Жизненный цикл: методы preload и create
После конструктора мы определяем методы жизненного цикла сцены. Метод preload запускается самым первым и предназначен для загрузки всех необходимых ассетов (изображений, звуков, данных) в кэш.
preload: function ()
{
this.load.image('face', 'assets/pics/bw-face.png');
},
Здесь мы используем менеджер загрузки this.load, доступный в контексте сцены. Метод .image('face', ...) загружает картинку и присваивает ей ключ 'face' для последующего использования.
Метод create вызывается один раз после успешной загрузки всех ресурсов из preload. Здесь происходит начальная настройка игрового мира: создание объектов, настройка физики, ввод данных.
create: function ()
{
this.face = this.add.image(400, 300, 'face');
}
Строка `this.face = this.add.image(400, 300, 'face');` делает следующее:
1. `this.add.image` — фабричный метод для создания объекта изображения.
2. `400, 300` — координаты X и Y для размещения центра изображения на холсте.
3. `'face'` — ключ изображения, загруженного ранее в `preload`.
4. `this.face = ...` — ссылка на созданный объект сохраняется в свойстве сцены, чтобы к нему можно было обратиться позже (например, для анимации).
Конфигурация игры и запуск
Отдельно от класса сцены определяется конфигурационный объект игры. В нём задаются основные параметры рендерера и, что самое важное, указывается, какой класс сцены будет запущен при старте.
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
backgroundColor: '#000000',
parent: 'phaser-example',
scene: MyScene // Указываем наш класс сцены
};
Ключевое свойство scene принимает не экземпляр, а сам класс (MyScene). Phaser сам создаст экземпляр этого класса при инициализации игры.
Финальный шаг — создание экземпляра игры с переданной конфигурацией. Этот вызов запускает весь движок.
const game = new Phaser.Game(config);
Что попробовать дальше
Использование Phaser.Class для создания сцен — это фундаментальный и структурированный подход. Он идеально подходит для разработчиков, предпочитающих чёткую иерархию и ООП-архитектуру. Для экспериментов попробуйте:
1. Добавить в класс метод update и заставить изображение двигаться, изменяя свойство this.face.x.
2. Создать второй, аналогичный класс сцены (например, MenuScene) и настроить их переключение с помощью this.scene.start().
3. Вынести общую логику (например, загрузку стандартных ассетов) в базовый класс сцены, от которого будут наследоваться MyScene и MenuScene.
