О чем этот пример
Плагины в Phaser позволяют инкапсулировать и переиспользовать игровую логику, например, управление движением объектов. Однако часто возникает необходимость включать и выключать эту логику динамически во время выполнения игры — например, по клику мыши или при смене состояния уровня. В этой статье мы разберем, как правильно создавать плагин с методами `start` и `stop`, и как управлять его активностью из основного кода сцены. Это полезно для оптимизации (отключение неиспользуемых систем) и гибкого контроля над игровыми процессами.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class MoveSpritePlugin extends Phaser.Plugins.BasePlugin {
constructor (pluginManager)
{
super(pluginManager);
this.sprite;
}
init ()
{
console.log('init');
}
start ()
{
console.log('start');
var eventEmitter = this.game.events;
eventEmitter.on('step', this.update, this);
}
stop ()
{
console.log('stop');
var eventEmitter = this.game.events;
eventEmitter.off('step', this.update);
}
setSprite (sprite)
{
this.sprite = sprite;
}
update (time, delta)
{
if (this.sprite)
{
this.sprite.x -= 0.2 * delta;
if (this.sprite.x < 0)
{
this.sprite.x = 800;
}
}
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
plugins: {
global: [
{ key: 'MoveSpritePlugin', plugin: MoveSpritePlugin, start: true }
]
},
scene: {
preload: preload,
create: create
}
};
let game = new Phaser.Game(config);
function preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('elephant', 'assets/sprites/elephant.png');
}
function create ()
{
let ele = this.add.image(400, 300, 'elephant');
let plugin = this.plugins.get('MoveSpritePlugin');
plugin.setSprite(ele);
this.input.on('pointerup', function (pointer) {
if (this.plugins.isActive('MoveSpritePlugin'))
{
this.plugins.stop('MoveSpritePlugin');
}
else
{
this.plugins.start('MoveSpritePlugin');
}
}, this);
}
Структура пользовательского плагина
Плагин в Phaser должен наследоваться от базового класса Phaser.Plugins.BasePlugin. Это дает доступ к менеджеру плагинов и жизненному циклу. В конструкторе мы вызываем super и можем инициализировать внутренние переменные, например, ссылку на спрайт.
Ключевые методы жизненного цикла:
- init(): Вызывается один раз при создании экземпляра плагина.
- start(): Запускает активную работу плагина. Здесь обычно подписываются на события игры.
- stop(): Останавливает плагин, отписываясь от событий и освобождая ресурсы.
class MoveSpritePlugin extends Phaser.Plugins.BasePlugin {
constructor(pluginManager) {
super(pluginManager);
this.sprite;
}
init() {
console.log('init');
}
start() {
console.log('start');
var eventEmitter = this.game.events;
eventEmitter.on('step', this.update, this);
}
stop() {
console.log('stop');
var eventEmitter = this.game.events;
eventEmitter.off('step', this.update);
}
}
Логика обновления и управление спрайтом
Плагин содержит метод update, который будет вызываться на каждом шаге игрового цикла (step), если плагин активен. Внутри мы проверяем, задан ли спрайт, и двигаем его по горизонтали с постоянной скоростью, учитывая delta для независимости от частоты кадров. Когда спрайт уходит за левый край экрана, он возвращается в правую часть.
Метод setSprite позволяет передать плагину любой спрайт для управления извне, что делает плагин универсальным.
setSprite(sprite) {
this.sprite = sprite;
}
update(time, delta) {
if (this.sprite) {
this.sprite.x -= 0.2 * delta;
if (this.sprite.x < 0) {
this.sprite.x = 800;
}
}
}
Регистрация плагина в конфигурации игры
Чтобы сделать плагин доступным глобально во всех сценах, его нужно указать в конфиге игры в разделе plugins.global. Ключевые параметры:
- key: Строковый идентификатор для доступа к плагину.
- plugin: Ссылка на класс плагина.
- start: Если true, плагин будет автоматически запущен после создания. В нашем примере это так, но позже мы можем его остановить.
const config = {
type: Phaser.AUTO,
plugins: {
global: [
{ key: 'MoveSpritePlugin', plugin: MoveSpritePlugin, start: true }
]
},
scene: {
preload: preload,
create: create
}
};
Использование плагина в сцене и управление состоянием
В сцене мы сначала загружаем изображение и создаем спрайт. Затем получаем экземпляр плагина по его ключу с помощью this.plugins.get('MoveSpritePlugin') и передаем ему спрайт для управления.
Далее мы настраиваем обработчик клика мыши (pointerup). Внутри проверяем, активен ли плагин в данный момент, с помощью this.plugins.isActive('MoveSpritePlugin'). В зависимости от результата либо останавливаем плагин методом stop, либо запускаем его методом start. Это позволяет toggle-управление (вкл/выкл) движением спрайта по клику.
function create() {
let ele = this.add.image(400, 300, 'elephant');
let plugin = this.plugins.get('MoveSpritePlugin');
plugin.setSprite(ele);
this.input.on('pointerup', function (pointer) {
if (this.plugins.isActive('MoveSpritePlugin')) {
this.plugins.stop('MoveSpritePlugin');
} else {
this.plugins.start('MoveSpritePlugin');
}
}, this);
}
Что попробовать дальше
Динамическое управление плагинами через start и stop — мощный инструмент для создания модульных и оптимизированных игр. Вы можете расширить пример: добавить несколько плагинов для разных типов движения (например, прыжки или патрулирование), управлять их активностью в зависимости от состояния игрока (бег, полет) или реализовать систему пауз, останавливая все второстепенные процессы. Экспериментируйте с подпиской на другие события, например postUpdate, или добавьте в плагин настройку скорости движения через параметры.
