О чем этот пример
В играх часто требуется определить, пересекаются ли объекты. Для проверки столкновений пуль, траекторий движения или границ уровня можно использовать линии. Встроенный модуль геометрии Phaser позволяет легко и эффективно проверять пересечение двух линий и находить точку, где это происходит. Этот подход гораздо производительнее, чем расчеты через физические тела, и идеально подходит для кастомных систем коллизий, визуализации лучей (ray casting) или редакторов уровней.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
graphics;
line2;
line1;
create ()
{
this.graphics = this.add.graphics();
this.line1 = new Phaser.Geom.Line(260, 200, 450, 450);
this.line2 = new Phaser.Geom.Line(300, 400, 500, 500);
this.graphics.lineStyle(2, 0x00ff00);
this.graphics.strokeLineShape(this.line1);
this.graphics.lineStyle(2, 0xffff00);
this.graphics.strokeLineShape(this.line2);
this.input.on('pointermove', pointer =>
{
this.line2.x2 = pointer.x;
this.line2.y2 = pointer.y;
});
}
update ()
{
Phaser.Geom.Line.Rotate(this.line1, 0.02);
this.graphics.clear();
this.graphics.fillStyle(0xffffff);
this.graphics.lineStyle(2, 0x00ff00);
this.graphics.strokeLineShape(this.line1);
const p = { x: 0, y: 0 };
if (Phaser.Geom.Intersects.LineToLine(this.line1, this.line2, p))
{
this.graphics.lineStyle(2, 0xff0000);
this.graphics.fillPointShape(p, 8);
}
else
{
this.graphics.lineStyle(2, 0xffff00);
}
this.graphics.strokeLineShape(this.line2);
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Создание сцены и инициализация линий
В методе create() инициализируется графика и две линии. Линия в Phaser определяется начальной и конечной точками (x1, y1, x2, y2). Первая линия (line1) статична по своим координатам, но будет вращаться. Вторая линия (line2) жестко закреплена в начальной точке, а ее конечная точка будет следовать за курсором мыши.
Используется объект Graphics для рисования примитивов. Сначала задается стиль линии, а затем она отрисовывается.
this.graphics = this.add.graphics();
this.line1 = new Phaser.Geom.Line(260, 200, 450, 450);
this.line2 = new Phaser.Geom.Line(300, 400, 500, 500);
this.graphics.lineStyle(2, 0x00ff00);
this.graphics.strokeLineShape(this.line1);
this.graphics.lineStyle(2, 0xffff00);
this.graphics.strokeLineShape(this.line2);
Слушатель события pointermove обновляет координаты конечной точки второй линии, делая ее интерактивной.
this.input.on('pointermove', pointer =>
{
this.line2.x2 = pointer.x;
this.line2.y2 = pointer.y;
});
Игровой цикл: вращение и проверка пересечения
В методе update() происходит основная логика. Сначала первая линия вращается вокруг своей начальной точки с помощью статического метода Phaser.Geom.Line.Rotate().
Phaser.Geom.Line.Rotate(this.line1, 0.02);
Затем холст Graphics полностью очищается, и первая линия перерисовывается. Ключевой этап — проверка пересечения с помощью Phaser.Geom.Intersects.LineToLine(). Этот метод принимает две линии и объект-результат `p`.
const p = { x: 0, y: 0 };
if (Phaser.Geom.Intersects.LineToLine(this.line1, this.line2, p))
Если линии пересекаются, метод возвращает true и записывает координаты точки пересечения в переданный объект `p. В противном случае возвращаетсяfalse`.
Важно: объект `pдолжен быть создан заранее и передан в метод третьим аргументом. Метод изменит его свойстваxиy` только в случае успешного обнаружения пересечения.
Визуальная обратная связь
На основе результата проверки меняется визуальное отображение. Если пересечение есть, стиль второй линии меняется на красный, а в вычисленной точке `p` рисуется закрашенная точка.
if (Phaser.Geom.Intersects.LineToLine(this.line1, this.line2, p))
{
this.graphics.lineStyle(2, 0xff0000);
this.graphics.fillPointShape(p, 8);
}
else
{
this.graphics.lineStyle(2, 0xffff00);
}
this.graphics.strokeLineShape(this.line2);
Точка рисуется методом fillPointShape(), который принимает объект с координатами и размер. Так пользователь сразу видит, когда линии пересекаются и где именно находится точка контакта. Это полезно для отладки и создания наглядных демонстраций.
Конфигурация игры и запуск
Стандартная конфигурация игры Phaser 3. Ключевые параметры: размер холста и указание на класс сцены, который содержит всю логику.
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Класс Example становится активной сценой игры. Весь код, описанный выше, выполняется в контексте этой сцены и ее методов жизненного цикла (create, update).
Что попробовать дальше
Метод Phaser.Geom.Intersects.LineToLine — мощный и легковесный инструмент для проверки пересечений. Он идеален для нефизических коллизий, например, для определения, пересек ли луч (Line) зону видимости врага или границу сектора. Для экспериментов попробуйте
- Сделать первую линию тоже подвижной, управляемой с клавиатуры
- Создать массив линий-препятствий и проверять пересечение с ними всех пуль
- Использовать точку пересечения `p` для запуска частиц или звукового эффекта при "попадании"
