О чем этот пример
При разработке игр часто возникает задача определить, попал ли игрок (или его клик) в сложную область объекта. Использование стандартных прямоугольных хитбоксов не всегда подходит для фигур неправильной формы. В этой статье мы рассмотрим, как с помощью метода `geom.contains` проверить, находится ли точка внутри полигона, что открывает возможности для создания интерактивных объектов со сложной геометрией, точных коллизий и нестандартных зон взаимодействия.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
const data = [ 0,20, 84,20, 84,0, 120,50, 84,100, 84,80, 0,80 ];
const r2 = this.add.polygon(400, 300, data, 0x9966ff).setOrigin(0, 0);
this.input.on('pointerdown', (pointer) => {
const x = pointer.worldX - r2.x;
const y = pointer.worldY - r2.y;
console.log(r2.geom.contains(x, y));
});
console.log(r2);
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Создание полигона и настройка сцены
Первым делом в методе create() сцены мы создаем игровой объект — полигон. Для этого используется метод this.add.polygon(). В качестве данных для полигона передается массив координат вершин.
const data = [ 0,20, 84,20, 84,0, 120,50, 84,100, 84,80, 0,80 ];
const r2 = this.add.polygon(400, 300, data, 0x9966ff).setOrigin(0, 0);
Здесь data — это плоский массив, где пары чисел представляют собой координаты X и Y каждой вершины полигона относительно его точки начала координат (origin). Объект создается в позиции (400, 300) на сцене и окрашивается в цвет 0x9966ff. Вызов .setOrigin(0, 0) устанавливает точку начала координат полигона в его левый верхний угол, что упрощает дальнейшие расчеты. Конфигурация игры задает стандартное окно 800x600 пикселей.
Обработка клика и преобразование координат
Далее мы настраиваем обработчик события клика (или касания) на сцене с помощью this.input.on('pointerdown', ...). Когда пользователь кликает, нам нужно проверить, попала ли точка клика внутрь нашего полигона.
this.input.on('pointerdown', (pointer) => {
const x = pointer.worldX - r2.x;
const y = pointer.worldY - r2.y;
console.log(r2.geom.contains(x, y));
});
Ключевой момент — преобразование координат. Свойства pointer.worldX и pointer.worldY дают нам координаты клика в мировой системе координат сцены. Однако метод geom.contains ожидает координаты относительно локальной системы координат самого полигона. Поэтому мы вычитаем из мировых координат позицию полигона (r2.x и r2.y). Это и дает нам координаты (x, y) относительно начала координат полигона.
Использование метода geom.contains
Самой проверкой занимается метод contains, который находится в свойстве geom объекта полигона r2. Это свойство содержит экземпляр класса Phaser.Geom.Polygon, представляющий геометрию фигуры.
console.log(r2.geom.contains(x, y));
Метод contains(x, y) возвращает булево значение: true, если переданная точка находится внутри полигона (или на его границе), и false — если снаружи. Алгоритм учитывает форму, заданную массивом data при создании. Результат проверки выводится в консоль, но в реальной игре его можно использовать для запуска игровой логики: начисления очков, открытия дверей, активации ловушек.
Практические аспекты и доступ к геометрии
Важно понимать, что метод geom.contains доступен не только для полигонов, но и для других геометрических объектов в Phaser, таких как Circle, Rectangle, Triangle. Это часть геометрической утилиты фреймворка.
console.log(r2);
Если вывести объект r2 в консоль, можно увидеть все его свойства, включая geom. Это полезно для отладки. Помните, что для корректной работы contains координаты точки должны быть приведены к локальной системе объекта. Если полигон трансформирован (повернут, масштабирован), его геометрия (r2.geom) автоматически обновляется, и метод продолжит работать корректно.
Что попробовать дальше
Метод geom.contains — это мощный и точный инструмент для проверки попадания точки в полигональную область. Он избавляет от необходимости использовать аппроксимацию фигур прямоугольниками или кругами, повышая реалистичность взаимодействия. Для экспериментов попробуйте: создать полигон в форме звезды или буквы и сделать его интерактивной кнопкой; реализовать нестандартную зону поражения для врага; комбинировать проверки для нескольких полигонов, создавая сложную составную область; или анимировать цвет полигона в зависимости от результата проверки contains.
