О чем этот пример

При разработке игр часто возникает задача определить, попал ли игрок (или его клик) в сложную область объекта. Использование стандартных прямоугольных хитбоксов не всегда подходит для фигур неправильной формы. В этой статье мы рассмотрим, как с помощью метода `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.