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

Работа с геометрией — неотъемлемая часть разработки игр. Определение пересечений, столкновений или простого совпадения фигур часто становится основой игровой механики. В этом примере мы разберем, как эффективно использовать метод `Phaser.Geom.Circle.Equals` для сравнения окружностей. Это знание пригодится для создания систем выделения объектов, простой коллизии или визуальной обратной связи при наведении, что делает интерфейс игры более отзывчивым и понятным для игрока.

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class Example extends Phaser.Scene
{
    create ()
    {
        const graphics = this.add.graphics({ fillStyle: { color: 0x00ff00 } });

        const circles = [];

        for (let x = 0; x < 8; x++)
        {
            for (let y = 0; y < 6; y++)
            {
                const size = Phaser.Math.Between(1, 5) * 10;
                circles.push(new Phaser.Geom.Circle(50 + x * 100, 50 + y * 100, size));
            }
        }

        const mouseCircle = new Phaser.Geom.Circle(-50, -50, 50);

        this.input.on('pointermove', pointer =>
        {

            // round position to 25 pixels
            const x = Math.round(pointer.x / 25) * 25;
            const y = Math.round(pointer.y / 25) * 25;

            mouseCircle.setPosition(x, y);

            redraw();
        });

        redraw();

        function redraw ()
        {
            graphics.clear();

            let strokeRed = false;

            for (let i = 0; i < circles.length; i++)
            {
                graphics.fillCircleShape(circles[i]);
                strokeRed = strokeRed || Phaser.Geom.Circle.Equals(mouseCircle, circles[i]);
            }

            if (strokeRed)
            {
                graphics.lineStyle(5, 0xff0000);
            }
            else
            {
                graphics.lineStyle(5, 0x0000ff);
            }

            graphics.strokeCircleShape(mouseCircle);
        }
    }
}

const config = {
    width: 800,
    height: 600,
    type: Phaser.AUTO,
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

Суть метода Circle.Equals

Метод Phaser.Geom.Circle.Equals выполняет строгое сравнение двух окружностей. Он возвращает true только если окружности идентичны по всем параметрам: координаты центра (x, y) и радиус (radius) должны совпадать с точностью до оператора строгого равенства (===).

Phaser.Geom.Circle.Equals(circleA, circleB);

В предоставленном примере этот метод является ключевым для определения, совпадает ли окружность, следующая за указателем мыши, с какой-либо из статических окружностей на сцене. Это наглядная демонстрация точного геометрического сравнения.

Разбор сцены и создание объектов

В начале метода create() создается объект graphics для отрисовки и массив circles. В двойном цикле генерируется сетка из 48 окружностей со случайным радиусом.

const graphics = this.add.graphics({ fillStyle: { color: 0x00ff00 } });
const circles = [];
for (let x = 0; x < 8; x++) {
    for (let y = 0; y < 6; y++) {
        const size = Phaser.Math.Between(1, 5) * 10;
        circles.push(new Phaser.Geom.Circle(50 + x * 100, 50 + y * 100, size));
    }
}

Также создается окружность mouseCircle, которая изначально помещена за пределы видимой области (-50, -50). Она будет следовать за курсором. Важно понимать, что Phaser.Geom.Circle — это объект данных, описывающий геометрическую фигуру, а не спрайт. Для его отображения используется объект Graphics.

Обработка движения мыши и привязка к сетке

Событие pointermove обновляет позицию mouseCircle. Однако, чтобы сравнение было наглядным и окружность «прилипала» к позициям статических кругов, координаты курсора округляются до шага в 25 пикселей.

this.input.on('pointermove', pointer => {
    const x = Math.round(pointer.x / 25) * 25;
    const y = Math.round(pointer.y / 25) * 25;
    mouseCircle.setPosition(x, y);
    redraw();
});

Этот прием — «сетка» или «привязка» (snapping) — часто используется в редакторах уровней или конструкторах. После обновления позиции вызывается функция redraw() для перерисовки сцены.

Логика сравнения и визуализации

Функция redraw() — сердце примера. Она очищает холст graphics и заново рисует все статические окружности зеленым цветом. В цикле происходит проверка на совпадение mouseCircle с каждой из окружностей в массиве.

let strokeRed = false;
for (let i = 0; i < circles.length; i++) {
    graphics.fillCircleShape(circles[i]);
    strokeRed = strokeRed || Phaser.Geom.Circle.Equals(mouseCircle, circles[i]);
}

Переменная strokeRed становится true, если метод Equals вернул true хотя бы для одной пары. Далее, в зависимости от результата сравнения, для mouseCircle устанавливается разный цвет обводки: красный при совпадении, синий — если совпадений нет.

if (strokeRed) {
    graphics.lineStyle(5, 0xff0000);
} else {
    graphics.lineStyle(5, 0x0000ff);
}
graphics.strokeCircleShape(mouseCircle);

Таким образом, визуальная обратная связь мгновенно показывает результат работы Circle.Equals.

Что попробовать дальше

Метод Phaser.Geom.Circle.Equals — это простой и надежный инструмент для точного сравнения окружностей. Как видно из примера, его можно эффективно использовать для создания интерактивных элементов, например, проверки точного попадания по цели или выделения объекта. Для экспериментов попробуйте заменить Circle.Equals на Circle.Equals (если бы такой был) или реализовать свою функцию сравнения с допустимой погрешностью (эпсилон) для радиуса или позиции, что полезно для более «гибких» игровых механик. Также можно применить эту логику к другим геометрическим фигурам, таким как Rectangle или Triangle, у которых есть аналогичные методы Equals.