О чем этот пример

Встроенные возможности 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 или реализуйте систему диалогов с поддержкой различных языков. Это отличный способ сделать ваш код чище и переиспользуемее.