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

Система событий в 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).