О чем этот пример
Проверка пересечений геометрических фигур — одна из основ игровой логики. Она нужна для определения попадания снаряда, коллизии луча и объектов или просто для создания визуальных эффектов. В этом примере мы разберем, как в 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. Используйте полученный булевый флаг не только для смены цвета, но и для игровой логики, например, уменьшения здоровья игрока.
