О чем этот пример
Зачем ограничивать интерактивную зону спрайта простым прямоугольником? В игровых интерфейсах и аркадных играх часто нужна более точная геометрия взаимодействия. В этой статье на практическом примере разберем, как задать для спрайта произвольную треугольную область (hit area), которая будет реагировать на наведение курсора. Этот прием полезен для создания нестандартных кнопок, реактивных элементов кораблей в космических симуляторах или сложных интерактивных объектов в point-and-click играх.
Версия 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('ship', 'assets/sprites/thrust_ship2.png');
}
create ()
{
const sprite = this.add.sprite(400, 300, 'ship').setScale(8);
const shape = new Phaser.Geom.Triangle.BuildEquilateral(16, 0, 30);
sprite.setInteractive(shape, Phaser.Geom.Triangle.Contains);
// Input Event listeners
sprite.on('pointerover', function ()
{
this.setTint(0x7878ff);
});
sprite.on('pointerout', function ()
{
this.clearTint();
});
}
}
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
pixelArt: true,
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Зачем нужны кастомные hit area?
По умолчанию в Phaser интерактивная область спрайта (setInteractive без параметров) совпадает с его ограничивающим прямоугольником (bounding box). Это может создавать проблемы:
* Для спрайтов непрямоугольной формы (например, космический корабль) зона клика будет включать "пустые" углы. * Пользовательский опыт ухудшается — курсор реагирует там, где визуально объекта нет.
Решение — определить собственную геометрическую область, точно соответствующую видимой части спрайта. В нашем примере это треугольник, построенный вокруг носовой части корабля.
Создание геометрической фигуры
Сначала создаем геометрическую форму. В Phaser для этого есть мощный модуль Phaser.Geom. Мы строим равносторонний треугольник.
const shape = new Phaser.Geom.Triangle.BuildEquilateral(16, 0, 30);
Разберем параметры метода BuildEquilateral:
* 16 — X-координата первой вершины треугольника **относительно центра спрайта**.
* `0` — Y-координата первой вершины.
* 30 — длина стороны треугольника.
Фигура создается в локальной системе координат спрайта (где его центр — это точка (0,0)). Это важно для последующего привязывания.
Привязка фигуры к спрайту
Ключевой метод — setInteractive. Он делает спрайт интерактивным, но в нашем случае с двумя аргументами.
sprite.setInteractive(shape, Phaser.Geom.Triangle.Contains);
* Первый аргумент (shape) — это созданный нами экземпляр Phaser.Geom.Triangle.
* Второй аргумент (Phaser.Geom.Triangle.Contains) — это функция-обработчик (callback или hit test callback), которая определяет, попала ли точка в фигуру. Phaser вызывает эту функцию каждый раз, когда нужно проверить пересечение курсора с областью. Мы используем встроенную статическую функцию Phaser.Geom.Triangle.Contains, которая возвращает true, если переданные координаты находятся внутри треугольника.
Теперь система проверки ввода будет использовать нашу треугольную область, а не прямоугольник спрайта.
Обработка событий ввода
После настройки интерактивной области можно вешать слушатели событий. В примере обрабатываются два события:
1. pointerover — курсор вошел в зону hit area.
2. pointerout — курсор вышел из зоны.
sprite.on('pointerover', function () {
this.setTint(0x7878ff); // Подсвечиваем спрайт синим оттенком
});
sprite.on('pointerout', function () {
this.clearTint(); // Убираем tint, возвращаем исходный цвет
});
Обратите внимание: внутри функций-обработчиков контекст (this) указывает на сам спрайт (sprite), что позволяет легко менять его свойства.
Что попробовать дальше
Использование кастомных hit area — это шаг к профессиональному полишу вашей игры. Механика становится точнее, а игрок — довольнее. Для экспериментов попробуйте:
* Заменить треугольник на круг (Phaser.Geom.Circle) или многоугольник (Phaser.Geom.Polygon).
* Создать сложную составную hit area из нескольких простых фигур.
* Динамически менять геометрию области в зависимости от состояния анимации спрайта (например, для удара мечом).
