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

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

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    create ()
    {
        const graphics = this.add.graphics({ lineStyle: { width: 5, color: 0xaa00aa } });

        const lines = [];

        for (let x = 0; x < 8; x++)
        {
            for (let y = 0; y < 6; y++)
            {
                const line = new Phaser.Geom.Line(x * 100 + 10, y * 100 + 50, x * 100 + 90, y * 100 + 50);

                Phaser.Geom.Line.Rotate(line, Phaser.Math.Between(0, 3) * (Math.PI / 4));

                lines.push(line);
            }
        }

        const mouseLine = new Phaser.Geom.Line(-80, 0, 0, 0);

        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;

            Phaser.Geom.Line.CenterOn(mouseLine, x, y);

            redraw();
        });

        redraw();

        function redraw ()
        {
            graphics.clear();

            let strokeRed = false;

            for (let i = 0; i < lines.length; i++)
            {
                graphics.strokeLineShape(lines[i]);
                strokeRed = strokeRed || Phaser.Geom.Line.Equals(mouseLine, lines[i]);
            }

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

            graphics.strokeLineShape(mouseLine);
        }
    }
}

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

const game = new Phaser.Game(config);

Подготовка сцены и создание линий

В начале метода create создается объект graphics для рисования и пустой массив lines, который будет хранить все статические линии. Затем в двойном цикле генерируется сетка из 48 линий (8 по горизонтали, 6 по вертикали). Каждая линия создается как объект Phaser.Geom.Line с начальными координатами и сразу поворачивается на случайный угол.

const graphics = this.add.graphics({ lineStyle: { width: 5, color: 0xaa00aa } });
const lines = [];

for (let x = 0; x < 8; x++)
{
    for (let y = 0; y < 6; y++)
    {
        const line = new Phaser.Geom.Line(x * 100 + 10, y * 100 + 50, x * 100 + 90, y * 100 + 50);
        Phaser.Geom.Line.Rotate(line, Phaser.Math.Between(0, 3) * (Math.PI / 4));
        lines.push(line);
    }
}

Создание интерактивной линии для мыши

Для отслеживания позиции курсора создается отдельная линия mouseLine. Её начальные координаты заданы относительно центра. Событие pointermove обновляет позицию этой линии, центрируя её на ближайшем узле сетки с шагом 100 пикселей. Это обеспечивает точное сравнение, так как статические линии также привязаны к этой сетке.

const mouseLine = new Phaser.Geom.Line(-80, 0, 0, 0);

this.input.on('pointermove', pointer =>
{
    const x = Math.floor(pointer.x / 100) * 100 + 50;
    const y = Math.floor(pointer.y / 100) * 100 + 50;
    Phaser.Geom.Line.CenterOn(mouseLine, x, y);
    redraw();
});

Логика сравнения и перерисовки

Функция redraw отвечает за отрисовку всех линий и визуальную обратную связь. Она очищает холст и рисует все статические линии из массива lines. Во время этого процесса с помощью Phaser.Geom.Line.Equals проверяется, совпадает ли mouseLine с любой из статических линий. Метод сравнивает начальные и конечные точки двух линий, возвращая true при полном совпадении.

function redraw ()
{
    graphics.clear();
    let strokeRed = false;

    for (let i = 0; i < lines.length; i++)
    {
        graphics.strokeLineShape(lines[i]);
        strokeRed = strokeRed || Phaser.Geom.Line.Equals(mouseLine, lines[i]);
    }

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

    graphics.strokeLineShape(mouseLine);
}

Если совпадение найдено, линия мыши рисуется красным цветом, иначе — фиолетовым. Это наглядно показывает результат работы метода сравнения.

Конфигурация игры и запуск

Код завершается стандартной конфигурацией Phaser Game. Указываются размеры холста, тип рендерера и класс сцены. Это основа для запуска любого примера Phaser.

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

const game = new Phaser.Game(config);

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

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