О чем этот пример
Встроенные возможности Phaser 3 огромны, но настоящая сила фреймворка раскрывается в его расширяемости. Создание собственных плагинов для сцены (Scene Plugins) позволяет инкапсулировать сложную логику, переиспользовать код между проектами и создавать чистую, модульную архитектуру. В этой статье мы разберем, как создать простой плагин для генерации случайных имён и интегрировать его в вашу игру.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class RandomNamePlugin extends Phaser.Plugins.ScenePlugin {
constructor (scene, pluginManager)
{
super(scene, pluginManager);
this.syllables1 = [ 'fro', 'tir', 'nag', 'bli', 'mon', 'zip' ];
this.syllables2 = [ 'fay', 'shi', 'zag', 'blarg', 'rash', 'izen' ];
this.current = this.syllables1;
}
changeSet ()
{
this.current = this.syllables2;
}
getNames (qty = 10)
{
let names = [];
for (let i = 0; i < qty; i++)
{
let name = '';
for (let i = 0; i < Phaser.Math.Between(2, 4); i++)
{
name = name.concat(Phaser.Utils.Array.GetRandom(this.current));
}
names.push(Phaser.Utils.String.UppercaseFirst(name));
}
return names;
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
plugins: {
scene: [
{ key: 'randomNamePlugin', plugin: RandomNamePlugin, mapping: 'randomPlugin' }
]
},
scene: {
create: create
}
};
let game = new Phaser.Game(config);
function create ()
{
let names = this.randomPlugin.getNames(10);
this.add.text(10, 10, names, { font: '16px Courier', fill: '#00ff00' });
this.randomPlugin.changeSet();
let moreNames = this.randomPlugin.getNames(10);
this.add.text(200, 10, moreNames, { font: '16px Courier', fill: '#ffff00' });
}
Что такое плагин для сцены?
Плагин для сцены (Scene Plugin) — это специальный класс, который расширяет Phaser.Plugins.ScenePlugin. Его ключевая особенность — прямая привязка к экземпляру сцены (this.scene), что дает ему доступ ко всем её методам и свойствам. После регистрации плагин становится доступен в любой сцене вашего проекта через заданное вами свойство (например, this.randomPlugin), что делает его использование очень удобным.
Такие плагины идеально подходят для функциональности, тесно связанной с жизненным циклом и отображением в сцене: управление специфичными UI-элементами, кастомные системы частиц, мини-игры или, как в нашем примере, генераторы контента.
Создаем класс плагина
Основу плагина составляет класс, наследующий от Phaser.Plugins.ScenePlugin. Конструктор принимает два обязательных аргумента: ссылку на сцену и менеджер плагинов. Внутри конструктора мы инициализируем состояние плагина.
class RandomNamePlugin extends Phaser.Plugins.ScenePlugin {
constructor (scene, pluginManager) {
super(scene, pluginManager);
this.syllables1 = [ 'fro', 'tir', 'nag', 'bli', 'mon', 'zip' ];
this.syllables2 = [ 'fay', 'shi', 'zag', 'blarg', 'rash', 'izen' ];
this.current = this.syllables1;
}
}
В этом примере мы создали два набора слогов и переменную current для хранения активного набора. Метод super(scene, pluginManager) вызывает конструктор родительского класса, что критически важно для корректной работы плагина.
Добавляем методы плагина
Логика плагина реализуется в его методах. Эти методы будут доступны из сцены после маппинга. Давайте добавим два метода: один для смены набора слогов, другой для генерации имён.
changeSet () {
this.current = this.syllables2;
}
getNames (qty = 10) {
let names = [];
for (let i = 0; i < qty; i++) {
let name = '';
for (let i = 0; i < Phaser.Math.Between(2, 4); i++) {
name = name.concat(Phaser.Utils.Array.GetRandom(this.current));
}
names.push(Phaser.Utils.String.UppercaseFirst(name));
}
return names;
}
Метод getNames использует встроенные утилиты Phaser: Phaser.Math.Between для выбора случайного количества слогов (от 2 до 4), Phaser.Utils.Array.GetRandom для выбора случайного слога из текущего набора и Phaser.Utils.String.UppercaseFirst для того, чтобы сделать первую букву имени заглавной. Параметр qty со значением по умолчанию делает метод гибким.
Регистрация плагина в конфигурации игры
Чтобы Phaser знал о нашем плагине и внедрил его в сцены, его необходимо зарегистрировать в глобальной конфигурации игры. Это делается в секции plugins.scene.
const config = {
// ... другие настройки (type, width, height)
plugins: {
scene: [
{
key: 'randomNamePlugin', // Уникальный ключ плагина в системе
plugin: RandomNamePlugin, // Ссылка на класс плагина
mapping: 'randomPlugin' // Имя свойства, под которым плагин будет доступен в сцене (this.randomPlugin)
}
]
},
scene: {
create: create
}
};
Ключевые параметры:
* key: внутренний идентификатор.
* plugin: класс, который нужно инстанцировать.
* mapping: самое важное — это имя, по которому вы будете обращаться к плагину из любой сцены (this.randomPlugin).
Использование плагина в сцене
После регистрации плагин автоматически становится доступен в контексте сцены (this). В функции create мы можем вызывать его методы как свои собственные.
function create ()
{
// 1. Генерируем 10 имён, используя первый набор слогов
let names = this.randomPlugin.getNames(10);
// Выводим зелёным цветом
this.add.text(10, 10, names, { font: '16px Courier', fill: '#00ff00' });
// 2. Меняем активный набор слогов в плагине
this.randomPlugin.changeSet();
// 3. Генерируем ещё 10 имён, но уже из второго набора
let moreNames = this.randomPlugin.getNames(10);
// Выводим жёлтым цветом
this.add.text(200, 10, moreNames, { font: '16px Courier', fill: '#ffff00' });
}
Код наглядно демонстрирует работу плагина: сначала генерируются имена из одного набора, затем набор меняется методом changeSet(), и следующая генерация использует уже другие слоги. Обратите внимание на простоту вызова: this.randomPlugin.getNames(10).
Что попробовать дальше
Создание плагинов для сцены — это мощный паттерн для структурирования кода в Phaser 3. Он помогает отделять игровую логику от логики конкретных механик или систем. Для экспериментов попробуйте расширить пример: добавьте метод для загрузки наборов слогов из JSON-файла, создайте плагин для управления сложным HUD или реализуйте систему диалогов с поддержкой различных языков. Это отличный способ сделать ваш код чище и переиспользуемее.
