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

В игровой разработке часто требуется проверять совпадение координат объектов: столкновения, выбор цели, определение попадания. Метод `equals` у вектора `Phaser.Math.Vector2` — это точный и эффективный инструмент для таких задач. В этой статье мы разберем, как использовать его на практическом примере, где курсор мыши ищет совпадение с набором точек на экране, и визуализируем результат.

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

Живой запуск

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

Исходный код


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

        const points = [];

        for (let i = 0; i < 100; i++)
        {
            const x = Phaser.Math.Between(1, 40) * 20;
            const y = Phaser.Math.Between(1, 30) * 20;
            points.push(new Phaser.Math.Vector2(x, y));
        }

        const pointerPoint = new Phaser.Math.Vector2();

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

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

            pointerPoint.setTo(x, y);

            redraw();
        });

        redraw();

        function redraw ()
        {
            graphics.clear();

            let strokeRed = false;

            for (let i = 0; i < points.length; i++)
            {
                graphics.fillPointShape(points[i], 15);
                strokeRed = strokeRed || pointerPoint.equals(points[i]);
            }

            if (strokeRed)
            {
                graphics.fillStyle(0xaa0000);
            }
            else
            {
                graphics.fillStyle(0x0000aa);
            }

            graphics.fillPointShape(pointerPoint, 15);
        }
    }
}

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

const game = new Phaser.Game(config);

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

В методе create сцены мы инициализируем графический объект graphics для отрисовки и создаем массив из 100 случайных точек. Координаты каждой точки генерируются с шагом в 20 пикселей, что создает сетчатый эффект.

const graphics = this.add.graphics({ fillStyle: { color: 0x2266aa } });
const points = [];

for (let i = 0; i < 100; i++)
{
    const x = Phaser.Math.Between(1, 40) * 20;
    const y = Phaser.Math.Between(1, 30) * 20;
    points.push(new Phaser.Math.Vector2(x, y));
}

Также создается вектор pointerPoint, который будет хранить текущую позицию курсора, приведенную к той же сетке.

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

Мы подписываемся на событие pointermove от системы ввода Phaser. При каждом движении мыши координаты курсора округляются до ближайшего значения, кратного 20 пикселям, и записываются в pointerPoint. Это гарантирует, что сравнение будет происходить по узлам сетки, а не по произвольным пикселям.

const pointerPoint = new Phaser.Math.Vector2();

this.input.on('pointermove', pointer =>
{
    const x = Math.round(pointer.x / 20) * 20;
    const y = Math.round(pointer.y / 20) * 20;
    pointerPoint.setTo(x, y);
    redraw();
});

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

Сравнение точек и визуализация

Функция redraw очищает холст и отрисовывает все точки из массива points. Ключевой момент — проверка совпадения pointerPoint с любой из точек с помощью метода equals. Этот метод возвращает true, если координаты X и Y двух векторов идентичны.

let strokeRed = false;

for (let i = 0; i < points.length; i++)
{
    graphics.fillPointShape(points[i], 15);
    strokeRed = strokeRed || pointerPoint.equals(points[i]);
}

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

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

Метод equals — это простой и надежный способ проверки точного совпадения координат в Phaser. Он идеально подходит для задач, требующих детерминированной проверки, например, в пошаговых стратегиях, головоломках или редакторах уровней. Для экспериментов попробуйте изменить шаг сетки, добавить сравнение с допуском (используя distance), или привязать логику к игровым объектам, например, для выделения юнитов.