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

Проверка пересечений геометрических фигур — одна из основ игровой логики. Она нужна для определения попадания снаряда, коллизии луча и объектов или просто для создания визуальных эффектов. В этом примере мы разберем, как в Phaser 3 работает проверка пересечения линии и окружности (`Phaser.Geom.Intersects.LineToCircle`). Вы увидите, как в реальном времени отслеживать столкновение движущейся мышью окружности с вращающейся линией, что идеально подходит для прототипирования механик стрельбы или обнаружения препятствий.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    graphics;
    circle;
    line;

    create ()
    {
        this.graphics = this.add.graphics();

        this.line = new Phaser.Geom.Line(260, 200, 450, 450);

        this.circle = new Phaser.Geom.Circle(300, 400, 60);

        this.graphics.lineStyle(2, 0x00ff00);
        this.graphics.strokeLineShape(this.line);
        this.graphics.lineStyle(2, 0xffff00);
        this.graphics.strokeCircleShape(this.circle);

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

            this.circle.x = pointer.x;
            this.circle.y = pointer.y;

        });
    }

    update ()
    {
        Phaser.Geom.Line.Rotate(this.line, 0.02);

        this.graphics.clear();
        this.graphics.lineStyle(2, 0x00ff00);
        this.graphics.strokeLineShape(this.line);

        if (Phaser.Geom.Intersects.LineToCircle(this.line, this.circle))
        {
            this.graphics.lineStyle(2, 0xff0000);
        }
        else
        {
            this.graphics.lineStyle(2, 0xffff00);
        }

        this.graphics.strokeCircleShape(this.circle);
    }
}

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

const game = new Phaser.Game(config);

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

В методе create() инициализируется сцена. Сначала создается объект Graphics для отрисовки фигур. Затем определяются две основные геометрические фигуры: линия (Phaser.Geom.Line) и окружность (Phaser.Geom.Circle).

Линия задается координатами начальной (260, 200) и конечной (450, 450) точек. Окружность определяется центром (300, 400) и радиусом 60 пикселей.

После создания фигуры сразу отрисовываются с помощью методов strokeLineShape и strokeCircleShape. Для каждой фигуры задается свой стиль линии (толщина и цвет).

this.graphics = this.add.graphics();
this.line = new Phaser.Geom.Line(260, 200, 450, 450);
this.circle = new Phaser.Geom.Circle(300, 400, 60);
this.graphics.lineStyle(2, 0x00ff00);
this.graphics.strokeLineShape(this.line);
this.graphics.lineStyle(2, 0xffff00);
this.graphics.strokeCircleShape(this.circle);

Затем настраивается слушатель события движения указателя (pointermove). При каждом движении мыши координаты центра окружности обновляются, что позволяет пользователю перемещать ее по холсту.

this.input.on('pointermove', pointer => {
    this.circle.x = pointer.x;
    this.circle.y = pointer.y;
});

Игровой цикл: вращение и проверка пересечений

Вся динамическая логика происходит в методе update(), который вызывается на каждом кадре.

Первым делом линия плавно вращается вокруг своего начала с помощью статического метода Phaser.Geom.Line.Rotate. Второй аргумент — угол поворота в радианах.

Phaser.Geom.Line.Rotate(this.line, 0.02);

Далее, чтобы избежать наложения графики, холст очищается вызовом this.graphics.clear(). После этого линия перерисовывается с исходным зеленым цветом.

this.graphics.clear();
this.graphics.lineStyle(2, 0x00ff00);
this.graphics.strokeLineShape(this.line);

Затем происходит ключевое действие — проверка пересечения текущей линии и окружности с помощью Phaser.Geom.Intersects.LineToCircle. Этот метод возвращает true или false.

if (Phaser.Geom.Intersects.LineToCircle(this.line, this.circle))

В зависимости от результата проверки, меняется стиль линии для окружности: красный цвет при пересечении, желтый — при его отсутствии. После установки стиля окружность отрисовывается заново.

{
    this.graphics.lineStyle(2, 0xff0000);
}
else
{
    this.graphics.lineStyle(2, 0xffff00);
}
this.graphics.strokeCircleShape(this.circle);

Как работает проверка пересечения

Метод Phaser.Geom.Intersects.LineToCircle — это готовая математическая функция. Внутри она решает задачу нахождения минимального расстояния от центра окружности до линии и сравнивает его с радиусом.

* Если расстояние меньше или равно радиусу, линия пересекает окружность или касается ее (возвращается true). * Если расстояние больше радиуса, пересечения нет (возвращается false).

Важно понимать, что метод работает с бесконечной в математическом смысле линией, проходящей через две заданные точки. Он проверяет пересечение именно с отрезком этой бесконечной прямой, который ограничен вашими точками (x1, y1) и (x2, y2). Это поведение отличается от проверки пересечения с лучом (Ray) или произвольным отрезком, где логика может быть иной.

Использование встроенного метода избавляет вас от необходимости самостоятельно реализовывать сложную математику, что ускоряет разработку и снижает риск ошибок.

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

Код завершается стандартной для Phaser 3 конфигурацией игры. В объекте config задаются размеры холста (800x600), тип рендерера (Phaser.AUTO), элемент-родитель в HTML и класс основной сцены (Example).

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

Именно эта конфигурация инициализирует игровой цикл, в котором будут вызываться методы create() (один раз) и update() (непрерывно).

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

Пример наглядно демонстрирует эффективность встроенных в Phaser 3 геометрических инструментов. Метод LineToCircle предоставляет простой и производительный способ проверки столкновений. **Идеи для экспериментов:** 1. Замените линию на луч (Phaser.Geom.Ray) и напишите собственную функцию проверки его пересечения с окружностью. 2. Добавьте несколько окружностей в массив и проверяйте пересечение линии с каждой из них, подсвечивая все пересекающиеся. 3. Реализуйте логику "разрушения": при пересечении удаляйте окружность со сцены или меняйте ее радиус. 4. Используйте полученный булевый флаг не только для смены цвета, но и для игровой логики, например, уменьшения здоровья игрока.