О чем этот пример
В играх часто возникает необходимость проверять столкновения сложных фигур, а не только стандартных прямоугольников и кругов. В этом примере мы разберем, как использовать геометрический модуль Phaser для определения пересечения между прямоугольником и треугольником. Этот метод полезен для создания нетривиальных хитбоксов у объектов, проверки попадания снаряда в сложную цель или определения зоны видимости NPC с углом обзора.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
graphics;
rectangle;
triangle;
create ()
{
this.graphics = this.add.graphics();
this.triangle = new Phaser.Geom.Triangle.BuildEquilateral(400, 320, 140);
this.rectangle = new Phaser.Geom.Rectangle(200, 150, 300, 200);
this.graphics.lineStyle(2, 0x00ff00);
this.graphics.strokeRectShape(this.rectangle);
this.graphics.lineStyle(2, 0xffff00);
this.graphics.strokeTriangleShape(this.triangle);
this.input.on('pointermove', pointer =>
{
Phaser.Geom.Triangle.CenterOn(this.triangle, pointer.x, pointer.y);
});
}
update ()
{
Phaser.Geom.Triangle.Rotate(this.triangle, 0.02);
this.graphics.clear();
this.graphics.lineStyle(2, 0x00ff00);
this.graphics.strokeRectShape(this.rectangle);
if (Phaser.Geom.Intersects.RectangleToTriangle(this.rectangle, this.triangle))
{
this.graphics.lineStyle(2, 0xff0000);
}
else
{
this.graphics.lineStyle(2, 0xffff00);
}
this.graphics.strokeTriangleShape(this.triangle);
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Настройка сцены и создание фигур
В методе create() мы подготавливаем сцену: создаем контейнер для рисования (Graphics) и определяем наши геометрические фигуры.
this.graphics = this.add.graphics();
this.triangle = new Phaser.Geom.Triangle.BuildEquilateral(400, 320, 140);
this.rectangle = new Phaser.Geom.Rectangle(200, 150, 300, 200);
Сначала создается объект this.graphics, который будет использоваться для отрисовки контуров фигур на сцене.
Далее, с помощью фабричного метода Phaser.Geom.Triangle.BuildEquilateral, создается равносторонний треугольник. Его центр будет в точке (400, 320), а длина стороны — 140 пикселей.
Прямоугольник создается с координатами верхнего левого угла (200, 150), шириной 300 и высотой 200 пикселей.
this.graphics.lineStyle(2, 0x00ff00);
this.graphics.strokeRectShape(this.rectangle);
this.graphics.lineStyle(2, 0xffff00);
this.graphics.strokeTriangleShape(this.triangle);
Здесь мы задаем стиль линии (толщина 2 пикселя, цвет зеленый) и рисуем контур прямоугольника. Затем меняем цвет на желтый и рисуем контур треугольника.
this.input.on('pointermove', pointer => {
Phaser.Geom.Triangle.CenterOn(this.triangle, pointer.x, pointer.y);
});
Эта строка добавляет обработчик события движения указателя мыши (или касания). При каждом движении центр треугольника перемещается в координаты курсора. Функция Phaser.Geom.Triangle.CenterOn пересчитывает вершины треугольника, сохраняя его форму и размер, но смещая центр масс в заданную точку.
Анимация и проверка пересечений
Основная логика обновления состояния игры находится в методе update(), который вызывается на каждом кадре.
Phaser.Geom.Triangle.Rotate(this.triangle, 0.02);
Первым делом треугольник вращается вокруг своего центра. Второй аргумент (0.02) — это угол поворота в радианах за один кадр.
this.graphics.clear();
this.graphics.lineStyle(2, 0x00ff00);
this.graphics.strokeRectShape(this.rectangle);
Перед отрисовкой нового кадра мы очищаем холст Graphics с помощью clear(). Затем заново рисуем прямоугольник зеленым цветом. Его положение статично.
if (Phaser.Geom.Intersects.RectangleToTriangle(this.rectangle, this.triangle))
{
this.graphics.lineStyle(2, 0xff0000);
}
else
{
this.graphics.lineStyle(2, 0xffff00);
}
this.graphics.strokeTriangleShape(this.triangle);
Это ключевой момент. Мы вызываем функцию Phaser.Geom.Intersects.RectangleToTriangle, передавая в нее ссылки на наш прямоугольник и треугольник. Функция возвращает true, если фигуры пересекаются (или одна содержится в другой). В зависимости от результата, мы выбираем цвет для обводки треугольника: красный при пересечении, желтый — когда фигуры разделены. После установки стиля рисуется контур треугольника.
Конфигурация игры и запуск
Код завершается стандартной для Phaser 3 конфигурацией и созданием экземпляра игры.
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Объект config задает основные параметры:
- width и height — размеры игрового холста.
- type — рендерер (WebGL или Canvas). Phaser.AUTO позволяет движку выбрать лучший из доступных.
- parent — ID HTML-элемента, в который будет встроен canvas.
- scene — класс основной сцены, которая будет запущена сразу после инициализации игры.
Создание экземпляра new Phaser.Game(config) запускает весь жизненный цикл.
Что попробовать дальше
Мы разобрали практический пример использования геометрического модуля Phaser для проверки пересечения двух произвольных фигур. Ключевая функция Phaser.Geom.Intersects.RectangleToTriangle выполняет всю сложную математику за вас. Для экспериментов попробуйте изменить размеры фигур, заменить равносторонний треугольник на произвольный с помощью new Phaser.Geom.Triangle(x1, y1, x2, y2, x3, y3), или добавить проверку пересечения с другими фигурами, например, используя CircleToTriangle. Это открывает путь к созданию сложных и точных систем коллизий.
