О чем этот пример
В игровой разработке часто требуется проверять столкновения объектов. Напрямую использовать физические движки для сценариев логики интерфейса, триггеров зон или упрощённых вычислений не всегда эффективно. Работа с геометрическими фигурами через `Phaser.Geom` предоставляет быстрый и лёгкий способ для таких проверок без затрат на полноценную физику. В этой статье мы разберём, как определить область пересечения двух прямоугольников, что полезно для создания зон активации, подсветки выбранной области или нефизических коллизий.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
const graphics = this.add.graphics();
const rectA = new Phaser.Geom.Rectangle(0, 0, 300, 100);
const rectB = new Phaser.Geom.Rectangle(150, 300, 500, 150);
const rectC = new Phaser.Geom.Rectangle();
graphics.lineStyle(1, 0xff0000);
graphics.strokeRectShape(rectA);
graphics.lineStyle(1, 0x00ff00);
graphics.strokeRectShape(rectB);
this.input.on('pointermove', pointer =>
{
graphics.clear();
Phaser.Geom.Rectangle.CenterOn(rectA, pointer.x, pointer.y);
Phaser.Geom.Rectangle.Intersection(rectA, rectB, rectC);
graphics.lineStyle(1, 0xff0000);
graphics.strokeRectShape(rectA);
graphics.lineStyle(1, 0x00ff00);
graphics.strokeRectShape(rectB);
if (!rectC.isEmpty())
{
graphics.lineStyle(1, 0xffff00);
graphics.strokeRectShape(rectC);
}
});
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и создание прямоугольников
В методе create() сцены мы сначала создаём объект Graphics для отрисовки фигур. Затем определяем два прямоугольника (rectA и rectB) и один пустой (rectC), который будет использоваться для результата.
Первый прямоугольник rectA изначально расположен в левом верхнем углу. Второй, rectB, находится ниже и правее. Третий, rectC, пока что пустой — его параметры будут вычислены позже.
Сразу после создания мы рисуем контуры первых двух прямоугольников разными цветами, чтобы визуализировать их начальное состояние.
const graphics = this.add.graphics();
const rectA = new Phaser.Geom.Rectangle(0, 0, 300, 100);
const rectB = new Phaser.Geom.Rectangle(150, 300, 500, 150);
const rectC = new Phaser.Geom.Rectangle();
graphics.lineStyle(1, 0xff0000);
graphics.strokeRectShape(rectA);
graphics.lineStyle(1, 0x00ff00);
graphics.strokeRectShape(rectB);
Обработка движения указателя и обновление позиции
Далее мы настраиваем обработчик события движения курсора мыши. При каждом движении указателя мы полностью очищаем холст graphics и заново перерисовываем фигуры с новыми параметрами.
Ключевое действие здесь — перемещение прямоугольника rectA в позицию курсора с помощью метода Phaser.Geom.Rectangle.CenterOn(). Это заставляет первый прямоугольник следовать за указателем мыши, что наглядно демонстрирует динамическое пересечение.
this.input.on('pointermove', pointer => {
graphics.clear();
Phaser.Geom.Rectangle.CenterOn(rectA, pointer.x, pointer.y);
Вычисление и отрисовка области пересечения
Сердце примера — вызов статического метода Phaser.Geom.Rectangle.Intersection(). Он принимает два исходных прямоугольника (rectA и rectB) и целевой прямоугольник (rectC), в который записывает результат. Если прямоугольники пересекаются, rectC получает координаты и размеры общей области. Если не пересекаются — он становится пустым.
После вычисления пересечения мы заново рисуем контуры исходных прямоугольников. Затем проверяем, не является ли rectC пустым, с помощью метода isEmpty(). Если пересечение существует, мы рисуем rectC жёлтым цветом поверх остальных.
Phaser.Geom.Rectangle.Intersection(rectA, rectB, rectC);
graphics.lineStyle(1, 0xff0000);
graphics.strokeRectShape(rectA);
graphics.lineStyle(1, 0x00ff00);
graphics.strokeRectShape(rectB);
if (!rectC.isEmpty()) {
graphics.lineStyle(1, 0xffff00);
graphics.strokeRectShape(rectC);
}
});
Конфигурация и запуск игры
Для запуска примера необходимо создать стандартную конфигурацию игры Phaser. В ней мы указываем размеры холста, тип рендерера и нашу сцену Example. После этого инстанциируем объект Game с этой конфигурацией.
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Использование Phaser.Geom.Rectangle.Intersection() — это эффективный способ для детекции пересечений прямоугольных областей в вашей игре. Этот подход идеален для создания невидимых триггерных зон, областей выбора или упрощённой логики столкновений, где полноценный физический движок был бы избыточен.
**Идеи для экспериментов:**
1. Добавьте проверку пересечения для более чем двух прямоугольников.
2. Используйте результат пересечения (rectC) для активации игровых событий, например, показа подсказки или воспроизведения звука.
3. Попробуйте привязать прямоугольники не к курсору, а к движущимся игровым спрайтам, чтобы визуализировать их "хитбоксы".
