О чем этот пример
При создании игр часто возникает задача обрабатывать клики не по спрайтам, а по произвольным областям экрана. Например, для интерактивных карт, пазлов или сложных интерфейсов. Phaser предоставляет для этого мощный инструмент — `Zone`. Эта статья покажет, как создавать невидимые интерактивные зоны и реагировать на взаимодействие с ними, что особенно полезно для создания точечных кликов по статичным изображениям или фонам.
Версия 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('donuts', 'assets/pics/donuts.jpg');
this.load.image('fork', 'assets/sprites/fork.png');
}
create ()
{
// Mmm, donuts
this.add.image(0, 0, 'donuts').setOrigin(0);
// A little fork sprite
const fork = this.add.image(1024, 600, 'fork').setOrigin(0.5, 0).setAngle(-20);
const label = this.add.text(0, 0, '', { font: '48px Arial Black', fill: '#c51b7d' });
label.setStroke('#de77ae', 8);
// And here's the real content.. some hit zones.
// One for each donut in the picture.
const zone1 = this.add.zone(0, 0, 345, 300).setOrigin(0).setName('Plain').setInteractive();
const zone2 = this.add.zone(345, 0, 310, 300).setOrigin(0).setName('Chocolate').setInteractive();
const zone3 = this.add.zone(655, 0, 369, 300).setOrigin(0).setName('Coffee\nand cream').setInteractive();
const zone4 = this.add.zone(0, 300, 330, 300).setOrigin(0).setName('Chocolate\nSprinkles').setInteractive();
const zone5 = this.add.zone(330, 300, 350, 300).setOrigin(0).setName('Strawberry').setInteractive();
const zone6 = this.add.zone(680, 300, 344, 300).setOrigin(0).setName('More\nSprinkles').setInteractive();
// And some events
this.input.on('gameobjectdown', (pointer, gameObject) =>
{
fork.x = pointer.x;
fork.y = pointer.y;
label.setText(gameObject.name);
label.x = gameObject.x;
label.y = gameObject.y;
});
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 1024,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Что такое Zone и зачем она нужна
Объект Zone в Phaser — это прямоугольная область на игровом холсте, которая не имеет графического представления, но может получать события ввода (клики, наведение). Это идеально подходит для случаев, когда нужно сделать интерактивными части фонового изображения, не создавая для этого отдельные спрайты.
В нашем примере изображение пончиков — это одна картинка. Чтобы обработать клик по каждому пончику отдельно, мы накладываем на них прозрачные зоны.
Создание интерактивных зон
Зоны создаются с помощью метода this.add.zone(x, y, width, height). Важно задать им имя с помощью .setName() и сделать интерактивными через .setInteractive(). Метод .setOrigin(0) устанавливает точку отсчёта координат зоны в её левый верхний угол, что упрощает позиционирование поверх изображения.
const zone1 = this.add.zone(0, 0, 345, 300).setOrigin(0).setName('Plain').setInteractive();
В коде примера мы создаём шесть зон, каждая покрывает свой пончик на изображении. Координаты и размеры подобраны вручную по картинке.
Обработка событий ввода
Чтобы зона реагировала на клики, нужно подписаться на события ввода. В примере используется событие gameobjectdown, которое срабатывает при нажатии кнопки мыши (или касании) на любом интерактивном игровом объекте, включая зоны.
this.input.on('gameobjectdown', (pointer, gameObject) => {
// Логика обработки
});
Обработчик получает два параметра: pointer (с информацией о точке взаимодействия) и gameObject (сам объект, по которому кликнули — в нашем случае это одна из зон).
Реакция на клик: визуальный фидбек
Внутри обработчика события мы выполняем две визуальные реакции, чтобы пользователь видел результат своего действия. Во-первых, перемещаем спрайт вилки в точку клика.
fork.x = pointer.x;
fork.y = pointer.y;
Во-вторых, отображаем название зоны (которое мы задали через setName) в виде текстовой метки, позиционируя её над зоной.
label.setText(gameObject.name);
label.x = gameObject.x;
label.y = gameObject.y;
Таким образом, при клике по пончику вилка "втыкается" в него, а рядом появляется подпись с его вкусом.
Что попробовать дальше
Зоны ввода (Zone) — это простой и эффективный способ добавить интерактивность в любое место вашей сцены, даже если там нет готового спрайта. Они отлично подходят для создания карт, интерактивных инфографик, скрытых объектов или нестандартных UI-элементов.
**Идеи для экспериментов:**
1. Сделайте зоны не прямоугольными, а круглыми, проверяя расстояние от точки клика до центра зоны.
2. Добавьте эффекты при наведении курсора на зону (событие gameobjectover).
3. Используйте зоны для создания невидимых кнопок или сенсорных областей в мобильной игре.
