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

Интеграция HTML-элементов в игровой canvas — мощный инструмент для создания сложных UI, меню или динамических подсказок без отрисовки текстур. Phaser 3 предоставляет DOM-контейнеры, позволяя анимировать и позиционировать элементы как обычные игровые объекты. В этой статье разберем, как добавить `div` в сцену, настроить его свойства и применить твины для плавной анимации, сохраняя все преимущества HTML/CSS.

Версия 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('einstein', 'assets/pics/ra-einstein.png');
    }

    create ()
    {
        const element = this.add.dom(400, 300, 'div', 'background-color: rgba(255, 255, 0, 0.5); width: 300px; height: 200px; font: 48px Arial; font-weight: bold', 'Phaser 3');

        element.setOrigin(1);

        const marker = this.add.rectangle(400, 300, 16, 16, 0xff00ff);

        this.tweens.add({
            targets: element,
            duration: 3000,
            angle: 360,
            scaleX: 2,
            scaleY: 2,
            ease: 'Sine.easeInOut',
            loop: -1,
            yoyo: true
        });
    }
}

const config = {
    type: Phaser.AUTO,
    scale: {
        _mode: Phaser.Scale.FIT,
        parent: 'phaser-example',
        width: 800,
        height: 600
    },
    dom: {
        createContainer: true
    },
    scene: Example
};

const game = new Phaser.Game(config);

Настройка DOM-контейнера в конфигурации

Для работы с DOM-элементами в Phaser 3 необходимо активировать специальный контейнер в настройках игры. Без этого система не сможет создавать и управлять HTML-объектами.

const config = {
    type: Phaser.AUTO,
    scale: {
        _mode: Phaser.Scale.FIT,
        parent: 'phaser-example',
        width: 800,
        height: 600
    },
    dom: {
        createContainer: true
    },
    scene: Example
};

Ключевой параметр dom.createContainer: true указывает Phaser создать скрытый HTML-контейнер, куда будут помещаться все добавляемые через this.add.dom элементы. Это обязательный шаг, иначе код вызовет ошибку.

Создание DOM-элемента в сцене

Метод this.add.dom() добавляет HTML-элемент в игровой мир. Он принимает координаты, тип тега, CSS-стили и текстовое содержимое.

const element = this.add.dom(400, 300, 'div', 'background-color: rgba(255, 255, 0, 0.5); width: 300px; height: 200px; font: 48px Arial; font-weight: bold', 'Phaser 3');

Здесь создается div с полупрозрачным желтым фоном, фиксированными размерами и крупным текстом. Элемент позиционируется в точке (400, 300) — это центр экрана при разрешении 800x600. Важно: стили передаются строкой, как в атрибуте style HTML.

element.setOrigin(1);

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

Визуализация точки отсчета

Чтобы наглядно увидеть, где находится центр трансформации DOM-элемента, добавим графический маркер — прямоугольник.

const marker = this.add.rectangle(400, 300, 16, 16, 0xff00ff);

Метод this.add.rectangle создает обычный игровой объект Phaser. Он размещается в тех же координатах (400, 300), что и DOM-элемент, и окрашивается в пурпурный цвет (0xff00ff). При запуске кода маркер останется неподвижным, демонстрируя точку, вокруг которой вращается div.

Анимация через твин-систему

Phaser позволяет анимировать DOM-элементы с помощью той же системы твинов, что и для спрайтов. Это обеспечивает плавность и согласованность анимаций в проекте.

this.tweens.add({
    targets: element,
    duration: 3000,
    angle: 360,
    scaleX: 2,
    scaleY: 2,
    ease: 'Sine.easeInOut',
    loop: -1,
    yoyo: true
});

- targets: element: указывает, что анимироваться будет наш DOM-объект. - angle: 360: полный оборот на 360 градусов. - scaleX: 2, scaleY: 2: увеличение размера в 2 раза по обеим осям. - ease: 'Sine.easeInOut': плавное ускорение и замедление анимации. - loop: -1: бесконечное повторение (значение -1). - yoyo: true: после завершения цикла анимация проигрывается в обратном порядке, создавая эффект "пульсации".

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

DOM-элементы в Phaser 3 открывают гибридный подход к разработке UI: вы можете использовать мощь CSS для стилизации и гибкость твинов для анимации. Для экспериментов попробуйте

  1. заменить div на input или button для интерактивных форм
  2. привязать движение элемента к курсору мыши через события
  3. комбинировать DOM-анимации с физикой спрайтов для нестандартных эффектов