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

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

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

Живой запуск

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

Исходный код


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

        const ellipses = [];

        for (let x = 0; x < 8; x++)
        {
            for (let y = 0; y < 6; y++)
            {
                const width = Phaser.Math.Between(4, 5) * 20;
                const height = Phaser.Math.Between(4, 5) * 20;

                ellipses.push(new Phaser.Geom.Ellipse(50 + x * 100, 50 + y * 100, width, height));
            }
        }

        const mouseEllipse = new Phaser.Geom.Ellipse(-50, -50, 100, 80);

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

            // round position to (100 * n + 50) pixels
            const x = Math.floor(pointer.x / 100) * 100 + 50;
            const y = Math.floor(pointer.y / 100) * 100 + 50;

            mouseEllipse.setPosition(x, y);

            redraw();
        });

        redraw();

        function redraw ()
        {
            graphics.clear();

            let strokeRed = false;

            for (let i = 0; i < ellipses.length; i++)
            {
                graphics.fillEllipseShape(ellipses[i]);
                strokeRed = strokeRed || Phaser.Geom.Ellipse.Equals(mouseEllipse, ellipses[i]);
            }

            if (strokeRed)
            {
                graphics.lineStyle(5, 0xaa0000);
            }
            else
            {
                graphics.lineStyle(5, 0x0000aa);
            }

            graphics.strokeEllipseShape(mouseEllipse);
        }
    }
}

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

const game = new Phaser.Game(config);

Суть метода Equals

Метод Phaser.Geom.Ellipse.Equals сравнивает два объекта эллипса. Он возвращает true, если их позиции (свойства `x,y) и размеры (width,height`) идентичны. Это точное сравнение, а не проверка пересечений или приблизительного наложения.

const isEqual = Phaser.Geom.Ellipse.Equals(ellipseA, ellipseB);

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

Подготовка сцены и сетки объектов

В create создается контейнер для рисования graphics и массив ellipses. Два вложенных цикла формируют сетку 8x6 эллипсов со случайными размерами в заданных пределах. Каждый эллипс создается через конструктор Phaser.Geom.Ellipse.

const ellipses = [];
for (let x = 0; x < 8; x++) {
    for (let y = 0; y < 6; y++) {
        const width = Phaser.Math.Between(4, 5) * 20;
        const height = Phaser.Math.Between(4, 5) * 20;
        ellipses.push(new Phaser.Geom.Ellipse(50 + x * 100, 50 + y * 100, width, height));
    }
}

Также создается отдельный эллипс mouseEllipse, который будет следовать за указателем.

Обработка движения курсора

На событие pointermove подписывается обработчик. Позиция курсора округляется до узлов сетки с шагом 100 пикселей, чтобы mouseEllipse "прилипал" к тем же координатам, что и статические эллипсы. Это обеспечивает возможность точного совпадения.

this.input.on('pointermove', pointer => {
    const x = Math.floor(pointer.x / 100) * 100 + 50;
    const y = Math.floor(pointer.y / 100) * 100 + 50;
    mouseEllipse.setPosition(x, y);
    redraw();
});

После обновления позиции вызывается функция redraw для перерисовки кадра.

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

Функция redraw сначала очищает холст graphics.clear(). Затем она рисует все эллипсы из массива и, в цикле, проверяет совпадает ли текущий mouseEllipse с любым из них, используя Phaser.Geom.Ellipse.Equals. Результат накапливается в переменной strokeRed.

let strokeRed = false;
for (let i = 0; i < ellipses.length; i++) {
    graphics.fillEllipseShape(ellipses[i]);
    strokeRed = strokeRed || Phaser.Geom.Ellipse.Equals(mouseEllipse, ellipses[i]);
}

В зависимости от результата (strokeRed), контур двигающегося эллипса рисуется красным (при совпадении) или синим цветом.

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

Метод Equals — это простой и надежный способ проверить полное геометрическое совпадение объектов. В игровых сценариях его можно адаптировать для активации триггеров, когда игрок помещает объект в строго определенную зону, или для проверки состояния расстановки предметов. Попробуйте изменить логику: сделайте проверку не на точное совпадение, а на пересечение областей, используя Phaser.Geom.Ellipse.Overlaps, или привяжите к событию клика для фиксации совпадения.