О чем этот пример
При работе с коллизиями и зонами интерактивности в Phaser 3 важно понимать, как трансформации объектов влияют на их хитбоксы. В этом примере мы разберем тонкость работы метода `setAngle()` для `Phaser.GameObjects.Zone` и почему визуальное представление может не совпадать с областью клика. Это знание поможет избежать коварных багов при создании интерактивных интерфейсов, вращающихся кнопок или нестандартных областей взаимодействия.
Версия 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('fork', 'assets/sprites/fork.png');
}
function create ()
{
// So we can see our zone
var r2 = this.add.rectangle(400, 300, 300, 150, 0x9966ff).setAngle(40);
var fork = this.add.image(1024, 600, 'fork').setOrigin(0.5, 0).setAngle(-20);
var zone1 = this.add.zone(400, 300).setSize(300, 150).setAngle(40).setInteractive();
this.input.on('gameobjectdown', function (pointer, gameObject) {
fork.x = pointer.x;
fork.y = pointer.y;
});
}
Подготовка сцены и создание визуала
В примере создается базовая сцена с двумя объектами: прямоугольником и изображением. Прямоугольник служит лишь визуальным ориентиром для зоны.
var r2 = this.add.rectangle(400, 300, 300, 150, 0x9966ff).setAngle(40);
Здесь setAngle(40) поворачивает прямоугольник на 40 градусов по часовой стрелке. Это чисто графическая операция.
Изображение вилки (fork) загружается и позиционируется за пределами экрана, также с поворотом в -20 градусов.
var fork = this.add.image(1024, 600, 'fork').setOrigin(0.5, 0).setAngle(-20);
Установка setOrigin(0.5, 0) смещает точку вращения и позиционирования к верхней середине спрайта.
Создание интерактивной зоны
Ключевой объект — Phaser.GameObjects.Zone. Это невидимый игровой объект, предназначенный для обработки событий ввода.
var zone1 = this.add.zone(400, 300).setSize(300, 150).setAngle(40).setInteractive();
Методы настройки зоны:
- setSize(300, 150) — задает ее размеры.
- setAngle(40) — **пытается** задать угол поворота.
- setInteractive() — активирует обработку событий ввода (кликов, наведений).
Важно: зона создается в той же позиции (400, 300) и с теми же параметрами, что и прямоугольник-индикатор.
Проблема: метод `setAngle()` для Zone
Здесь и кроется суть примера. В отличие от Phaser.GameObjects.Rectangle или Image, у объекта Zone **нет визуального представления**. Метод setAngle() существует в его API, но он **не влияет на форму или положение хитбокса** (области взаимодействия).
Хитбокс зоны остается простым неповернутым прямоугольником, описываемым методом setSize(). Он не вращается вместе с визуальным индикатором (прямоугольником r2).
Проверьте это сами: кликайте вокруг видимого повернутого фиолетового прямоугольника. Перемещаться будет только вилка, и область клика будет строго прямоугольной, ориентированной по осям мира.
Обработка клика и демонстрация
В сцене слушается событие gameobjectdown, которое срабатывает при клике на любой интерактивный объект (в нашем случае — на зону zone1).
this.input.on('gameobjectdown', function (pointer, gameObject) {
fork.x = pointer.x;
fork.y = pointer.y;
});
Функция-обработчик перемещает изображение вилки в координаты клика (pointer.x, pointer.y). Это наглядно показывает, где именно система «видит» зону. Вы увидите, что вилка перемещается только при клике внутри неповернутого прямоугольника, а не внутри повернутого фиолетового контура.
Как создать повернутую зону взаимодействия?
Если вам необходима именно повернутая область для ввода, используйте другие объекты:
1. **Повернутый Rectangle с setInteractive():** Он имеет и визуал, и корректно повернутый хитбокс.
var interactiveRect = this.add.rectangle(400, 300, 300, 150, 0x9966ff).setAngle(40).setInteractive();
2. **Использование setHitArea для кастомной геометрии:** Для сложных форм можно определить полигональную область.
zone.setInteractive({ hitArea: myPolygon, hitAreaCallback: Phaser.Geom.Polygon.Contains });
Для Zone же основное назначение — логические, невидимые и обычно не вращающиеся области на сцене (например, триггеры входа в комнату).
Что попробовать дальше
Метод setAngle() объекта Zone не изменяет его область взаимодействия — она всегда остается axis-aligned (выровненной по осям) прямоугольной областью, заданной setSize(). Для создания интерактивных повернутых элементов используйте графические объекты (Rectangle, Image, Sprite) с включенным setInteractive(). Поэкспериментируйте: замените Zone на Rectangle в примере и убедитесь, что клик теперь корректно работает в повернутых границах.
