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

Контейнеры в 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('buttonBG', 'assets/sprites/button-bg.png');
        this.load.image('buttonText', 'assets/sprites/button-text.png');
    }

    create ()
    {
        const bg = this.add.image(0, 0, 'buttonBG');
        const text = this.add.image(0, 0, 'buttonText');

        const container = this.add.container(400, 300, [ bg, text ]);

        container.setSize(bg.width, bg.height);

        container.setInteractive();

        container.on('pointerover', () =>
        {

            bg.setTint(0x44ff44);

        });

        container.on('pointerout', () =>
        {

            bg.clearTint();

        });
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#010101',
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

Почему контейнер не кликабелен из коробки?

В Phaser Container — это объект, который группирует другие игровые объекты для удобного трансформирования. Но его интерактивность (setInteractive) по умолчанию не определена. Даже если добавить интерактивность, хитрей (область реакции на мышь) будет нулевым, если не задать геометрию.

const container = this.add.container(400, 300, [ bg, text ]);
container.setInteractive(); // Без указания хитрея события не сработают

Задаем размер интерактивной области

Ключевой метод — container.setSize(width, height). Он устанавливает прямоугольную область для взаимодействия с контейнером. В нашем примере мы берем размеры фонового спрайта кнопки, чтобы хитрей точно соответствовал её видимой части.

container.setSize(bg.width, bg.height);

После этого вызов setInteractive() сделает контейнер чувствительным к событиям мыши именно в пределах заданного прямоугольника, расположенного относительно позиции контейнера.

Обработка событий pointerover и pointerout

Теперь к контейнеру можно привязать стандартные события ввода Phaser. В примере мы меняем оттенок фонового спрайта при наведении и убираем его, когда курсор уходит. Обратите внимание: события обрабатываются на уровне контейнера, а изменения применяются к его дочернему объекту bg.

container.on('pointerover', () => {
    bg.setTint(0x44ff44); // Зеленоватый оттенок
});

container.on('pointerout', () => {
    bg.clearTint(); // Возвращаем исходный цвет
});

Этот подход избавляет от необходимости делать интерактивным каждый спрайт в группе.

Собираем всё вместе

Вот полный код метода create. Мы создаем два спрайта, помещаем их в контейнер, задаем контейнеру хитрей по размеру фона и добавляем обработчики событий. Позиция контейнера (400, 300) становится центром для всей группы и её интерактивной области.

create ()
{
    const bg = this.add.image(0, 0, 'buttonBG');
    const text = this.add.image(0, 0, 'buttonText');
    const container = this.add.container(400, 300, [ bg, text ]);

    container.setSize(bg.width, bg.height);
    container.setInteractive();

    container.on('pointerover', () => { bg.setTint(0x44ff44); });
    container.on('pointerout', () => { bg.clearTint(); });
}

Что попробовать дальше

Использование setSize для контейнера — простой способ добавить интерактивность сложным составным объектам. Для экспериментов попробуйте

  1. Задать хитрей меньше или больше спрайта
  2. Использовать setInteractive с объектом геометрии для более сложных форм
  3. Добавить событие pointerdown для реализации нажатия кнопки
  4. Сделать интерактивным контейнер, внутри которого уже есть интерактивные дети, и посмотреть на всплытие событий