О чем этот пример
При разработке игр на Phaser часто возникают ситуации, когда интерактивные элементы перестают реагировать на пользовательский ввод. Это может быть связано с тем, что другие DOM-элементы на странице перекрывают игровое поле или сами границы интерактивной зоны объекта настроены некорректно. Понимание принципов работы системы ввода и настройки bounds (границ) критически важно для создания отзывчивого геймплея. В этой статье мы разберем на примере, как Phaser обрабатывает события ввода и что делать, если взаимодействие внезапно прекращается.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
var config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: {
preload: preload,
create: create
}
};
var game = new Phaser.Game(config);
function preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/skies/background1.png');
}
function create ()
{
this.add.image(400, 300, 'bg');
var r4 = this.add.rectangle(200, 400, 148, 148, 0xff6699);
r4.setInteractive();
r4.on('pointerover', () => {
r4.setFillStyle(0x9966ff);
})
r4.on('pointerout', () => {
r4.setFillStyle(0xff6699);
})
}
setTimeout(() => {
document.body.prepend(document.createElement("INPUT"))
}, 4000);
Проблема: исчезновение интерактивности
Рассмотрим простую сцену. В ней создается прямоугольник r4, который меняет цвет при наведении курсора. Однако через 4 секунды после старта игры на страницу программно добавляется элемент <input>. Этот элемент, будучи обычным DOM-узлом, может перехватывать события мыши, из-за чего интерактивность игрового прямоугольника теряется – курсор больше не вызывает смену цвета.
Это классический пример конфликта между DOM и Canvas. События мыши, которые Phaser ловит на уровне canvas, больше не доходят до него, так как их перехватывает новый элемент, появившийся поверх.
Решение: настройка границ ввода (Input Bounds)
Phaser предоставляет простой механизм для решения этой проблемы – объект input и его методы для управления границами ввода. Границы ввода определяют область на странице, в которой Phaser будет слушать события мыши, касаний и клавиатуры.
Чтобы указать системе ввода, что нужно отслеживать события только в пределах канваса игры, необходимо явно задать его границы. Это делается в методе create сцены.
function create() {
// ... создание фона и интерактивных объектов ...
// Устанавливаем границы ввода равными границам игрового канваса
this.input.setHitArea(this.sys.canvas);
}
Метод this.input.setHitArea() принимает DOM-элемент (в данном случае сам canvas) или объект с координатами. После этой настройки события мыши будут обрабатываться Phaser'ом только внутри указанной области, даже если поверх появились другие HTML-элементы.
Детальная настройка границ
Иногда нужно ограничить ввод не всем канвасом, а его конкретной областью. Например, для игры в оконном режиме или при наличии нескольких интерактивных зон. Для этого можно передать в setHitArea объект с координатами прямоугольной области.
function create() {
// ... создание фона и интерактивных объектов ...
// Устанавливаем границы ввода в виде прямоугольника {x, y, width, height}
this.input.setHitArea({ x: 100, y: 100, width: 600, height: 400 });
}
В этом примере Phaser будет реагировать на события мыши только внутри прямоугольника с началом в точке (100, 100) и размерами 600x400 пикселей. Все, что вне этой зоны, системой ввода игнорируется.
Важно: координаты области задаются относительно *страницы*, а не относительно канваса. Это нужно учитывать при сложной вёрстке.
Практический пример: защита от DOM-вторжений
Вернемся к исходному примеру. Добавим настройку границ ввода, чтобы защитить интерактивность прямоугольника от вновь создаваемого DOM-элемента.
function create() {
this.add.image(400, 300, 'bg');
var r4 = this.add.rectangle(200, 400, 148, 148, 0xff6699);
r4.setInteractive();
r4.on('pointerover', () => {
r4.setFillStyle(0x9966ff);
});
r4.on('pointerout', () => {
r4.setFillStyle(0xff6699);
});
// КРИТИЧЕСКИ ВАЖНАЯ СТРОКА: Защищаем интерактивность канваса
this.input.setHitArea(this.sys.canvas);
}
После этого, даже когда элемент <input> появится поверх игры, события наведения (pointerover) и увода (pointerout) курсора с прямоугольника будут корректно обрабатываться движком, так как границы ввода жестко привязаны к канвасу.
Что попробовать дальше
Явная настройка границ ввода (input bounds) – это простой, но мощный инструмент для обеспечения стабильной интерактивности в играх на Phaser, особенно когда игра встроена в сложную веб-страницу с динамическим контентом. Для экспериментов попробуйте
- Создать несколько интерактивных зон с разными
hitAreaи переключаться между ними в runtime - Связать границы ввода с камерой, чтобы интерактивной была только видимая область игрового мира
- Реализовать свою логику проверки попадания курсора в объект на основе пользовательских bounds
