О чем этот пример
Создание динамических интерфейсов и эффектов в играх часто требует выхода за пределы стандартных игровых объектов. Phaser 3 предоставляет мощный инструмент `add.dom()` для интеграции и анимации обычных HTML-элементов прямо на канвасе игры. Эта техника открывает двери для создания нестандартных меню, HUD с плавными трансформациями и сложных визуальных эффектов, которые сложно реализовать на спрайтах. В этой статье мы разберем, как добавить DOM-элемент в сцену и применить к нему твин с искажением (skew), создавая живой, пульсирующий эффект, который отлично сочетается с игровым фоном. Это практический пример, который можно сразу адаптировать под свои нужды.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
element;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('einstein', 'assets/pics/ra-einstein.png');
}
create ()
{
const div = document.createElement('div');
div.style = 'background-color: lime; width: 220px; height: 100px; font: 48px Arial; font-weight: bold';
div.innerText = 'Phaser 3';
this.element = this.add.dom(400, 300, div);
this.tweens.add({
targets: this.element,
skewX: 1.1,
skewY: 0.4,
duration: 3000,
ease: 'Sine.easeInOut',
loop: -1,
yoyo: true
});
this.add.image(400, 300, 'einstein');
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
dom: {
createContainer: true
},
scene: Example
};
const game = new Phaser.Game(config);
Настройка проекта и загрузка ресурсов
Для работы с DOM-элементами в Phaser 3 необходимо включить соответствующую опцию в конфигурации игры. Без этого система dom будет недоступна.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
dom: {
createContainer: true // Ключевая опция для активации DOM-системы
},
scene: Example
};
В методе preload() загружается фоновое изображение. Обратите внимание, что DOM-элемент не требует загрузки через this.load, так как создается динамически средствами браузера.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('einstein', 'assets/pics/ra-einstein.png');
}
Создание и добавление DOM-элемента в сцену
В методе create() происходит основная магия. Сначала мы создаем нативный HTML-элемент div и задаем ему стили через свойство style, как в обычной веб-разработке.
const div = document.createElement('div');
div.style = 'background-color: lime; width: 220px; height: 100px; font: 48px Arial; font-weight: bold';
div.innerText = 'Phaser 3';
Затем этот элемент добавляется в игровой мир с помощью метода this.add.dom(x, y, element). Он позиционируется относительно центра сцены (400, 300) и становится полноценным объектом сцены, который можно анимировать.
this.element = this.add.dom(400, 300, div);
После этого на сцену добавляется фоновое изображение, которое будет находиться под нашим DOM-объектом, создавая композицию.
Анимация искажения с помощью твинов
Phaser Tween Manager позволяет анимировать свойства объектов, включая DOM-элементы. В данном примере анимируются свойства skewX и skewY, которые отвечают за наклон элемента по соответствующим осям.
this.tweens.add({
targets: this.element, // Цель анимации - наш DOM-объект
skewX: 1.1, // Конечное значение искажения по оси X (в радианах)
skewY: 0.4, // Конечное значение искажения по оси Y
duration: 3000, // Длительность анимации в миллисекундах
ease: 'Sine.easeInOut', // Функция плавности для мягкого старта и остановки
loop: -1, // Бесконечный цикл анимации
yoyo: true // Анимация проигрывается и в обратном направлении
});
Параметр yoyo: true заставляет твин "отматываться" назад после завершения, а loop: -1 запускает этот процесс заново бесконечно. В результате элемент плавно искажается и возвращается в исходное состояние, создавая гипнотический эффект.
Особенности работы с DOM в Phaser
Важно понимать, что DOM-объект, созданный через add.dom(), интегрирован в систему отображения Phaser. Это означает:
1. Он участвует в порядке отрисовки (depth). В примере изображение Эйнштейна добавлено после DOM-элемента, поэтому оно оказывается под ним. 2. К нему можно применять трансформации, доступные для игровых объектов Phaser: позицию, масштаб, вращение, прозрачность и, как мы видели, искажение. 3. С ним можно взаимодействовать, добавляя слушатели событий мыши или клавиатуры.
Однако, для сложных CSS-анимаций или фильтров может потребоваться обращаться непосредственно к свойству this.element.node, которое содержит ссылку на исходный HTML-элемент.
Что попробовать дальше
Интеграция DOM-элементов через this.add.dom() — это мощный мост между игровым миром Phaser и возможностями CSS. Вы можете создавать текст со сложными стилями, интерактивные кнопки или информационные панели, которые было бы трудно реализовать на текстурах.
Для экспериментов попробуйте:
- Анимировать другие свойства, например scaleX/scaleY или alpha.
- Применить CSS-фильтры (blur, hue-rotate) через this.element.node.style.
- Создать сложный интерфейс с несколькими элементами и анимировать их последовательно с помощью цепочек твинов (tween.chain()).
- Обрабатывать клики по элементу, добавляя событие 'click' к this.element.node.
