О чем этот пример
Система событий в Phaser — мощный инструмент для организации взаимодействия между компонентами игры. Однако многие разработчики не используют её на полную мощность, ограничиваясь простыми вызовами без передачи данных. В этой статье разберём, как правильно передавать аргументы при генерации событий, что позволит создавать более гибкие и поддерживаемые игровые системы. Вы научитесь декомпозировать логику и уменьшать связность кода.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('plush', 'assets/pics/profil-sad-plush.png');
}
create ()
{
this.events.on('addImage', this.handler, this);
// The handler function will be sent 2 arguments: x and y
this.events.emit('addImage', 200, 300);
this.events.emit('addImage', 400, 300);
this.events.emit('addImage', 600, 300);
}
handler (x, y)
{
this.add.image(x, y, 'plush');
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Зачем передавать аргументы в события?
Представьте ситуацию: вам нужно создать несколько одинаковых объектов в разных позициях. Можно вызывать метод создания для каждого объекта отдельно, но это дублирует код. Гораздо эффективнее создать событие с параметрами и генерировать его с разными данными.
Такой подход позволяет:
- Централизовать логику обработки (все объекты создаются одним методом).
- Упростить добавление новых вызовов (просто emit с новыми координатами).
- Отделить код, который инициирует действие, от кода, который его выполняет.
В примере событие addImage будет обработано методом handler, который получит координаты для размещения изображения.
Регистрация обработчика события
Перед тем как генерировать события, нужно подписаться на них. В Phaser за события сцены отвечает объект this.events. Метод on регистрирует функцию-обработчик для конкретного имени события.
this.events.on('addImage', this.handler, this);
Здесь:
- `'addImage'` — произвольное имя события (тип).
- `this.handler` — функция, которая будет вызвана при срабатывании события.
- `this` — контекст, в котором будет выполнена функция-обработчик. Это важно, чтобы внутри `handler` мы могли использовать `this.add.image`.
Без указания контекста this внутри handler мог бы стать неопределённым (undefined).
Генерация события с аргументами
После регистрации обработчика можно генерировать события. Метод emit делает именно это. Первый аргумент — имя события, остальные — данные, которые будут переданы в обработчик.
this.events.emit('addImage', 200, 300);
this.events.emit('addImage', 400, 300);
this.events.emit('addImage', 600, 300);
Каждый вызов emit приводит к выполнению функции handler. В первый раз ей будут переданы числа 200 и 300, во второй — 400 и 300, и так далее. Таким образом, один обработчик может выполнять одну и ту же операцию (добавление изображения), но с разными входными данными.
Функция-обработчик и её параметры
Функция-обработчик объявляется как обычный метод класса. Количество и порядок её параметров должны соответствовать аргументам, передаваемым в emit после имени события.
handler (x, y)
{
this.add.image(x, y, 'plush');
}
В данном случае:
- `x` — первый аргумент после имени события (координата X).
- `y` — второй аргумент (координата Y).
- 'plush' — ключ изображения, загруженного в preload.
Метод this.add.image создаёт игровой объект Image и размещает его в указанных координатах. Благодаря контексту, переданному в on, мы имеем доступ к API сцены.
Что попробовать дальше
Передача аргументов в события — это простой, но мощный паттерн, который делает код чище и модульнее. Вы можете использовать его не только для создания объектов, но и для передачи любых данных: ID противника, количество урона, текстовое сообщение.
Для экспериментов попробуйте:
1. Передавать в событие не два, а три или четыре аргумента (например, ключ спрайта и его масштаб).
2. Создать несколько разных обработчиков для одного события.
3. Генерировать события из других сцен или плагинов, используя глобальную шину событий игры (this.game.events).
