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

В играх постоянно требуется проверять пересечение объектов — для определения столкновений, зон видимости или триггеров событий. Phaser предоставляет для этого удобные инструменты геометрического модуля. В этой статье мы разберем, как находить область пересечения двух прямоугольников и визуализировать её в реальном времени, что станет основой для ваших систем коллизий и взаимодействий.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    create ()
    {
        const graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x0000aa } });

        const rect = new Phaser.Geom.Rectangle(250, 200, 300, 200);
        const pointerRect = new Phaser.Geom.Rectangle(450, 350, 150, 100);

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

            Phaser.Geom.Rectangle.CenterOn(pointerRect, pointer.x, pointer.y);

            redraw();
        });

        redraw();

        function redraw ()
        {
            graphics.clear();

            graphics.strokeRectShape(rect);
            graphics.strokeRectShape(pointerRect);

            const intersection = Phaser.Geom.Intersects.GetRectangleIntersection(rect, pointerRect);

            graphics.lineStyle(2, 0xaa0000);
            graphics.strokeRectShape(intersection);
        }
    }
}

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

const game = new Phaser.Game(config);

Создание геометрии и графики

В методе create() сцены мы сначала создаем объект Graphics для отрисовки фигур. Затем определяем два прямоугольника: статичный (rect) и подвижный (pointerRect), который будет следовать за курсором.

const graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x0000aa } });
const rect = new Phaser.Geom.Rectangle(250, 200, 300, 200);
const pointerRect = new Phaser.Geom.Rectangle(450, 350, 150, 100);

Объекту graphics задается стиль синей линии толщиной 2 пикселя. Прямоугольники создаются с указанием координат X, Y, ширины и высоты. Пока это лишь математические объекты в памяти, не отрисованные на экране.

Обработка движения указателя

Мы подписываемся на событие pointermove от ввода (this.input). При каждом движении мыши или касании центр подвижного прямоугольника (pointerRect) перемещается в координаты курсора с помощью статического метода Phaser.Geom.Rectangle.CenterOn(). После обновления позиции вызывается функция redraw() для перерисовки кадра.

this.input.on('pointermove', pointer => {
    Phaser.Geom.Rectangle.CenterOn(pointerRect, pointer.x, pointer.y);
    redraw();
});

Это обеспечивает интерактивность: прямоугольник следует за указателем. Метод CenterOn() изменяет координаты переданного прямоугольника так, чтобы его центр совпадал с заданными точками pointer.x и pointer.y.

Функция перерисовки и визуализация

Функция redraw() сначала очищает холст graphics от предыдущего кадра. Затем она отрисовывает контуры обоих исходных прямоугольников с помощью strokeRectShape(), используя заданный ранее синий стиль линии.

function redraw() {
    graphics.clear();
    graphics.strokeRectShape(rect);
    graphics.strokeRectShape(pointerRect);

После этого происходит самое важное — вычисление пересечения. Мы вызываем Phaser.Geom.Intersects.GetRectangleIntersection(), передавая два прямоугольника. Этот метод возвращает новый объект Phaser.Geom.Rectangle, который представляет собой область пересечения исходных фигур. Если прямоугольники не пересекаются, метод вернет null.

const intersection = Phaser.Geom.Intersects.GetRectangleIntersection(rect, pointerRect);

Визуализация области пересечения

После вычисления пересечения мы меняем стиль линии на красный (0xaa0000) и отрисовываем полученный прямоугольник intersection. Если пересечения нет (intersection равен null), метод strokeRectShape() ничего не нарисует, и красный прямоугольник не появится.

graphics.lineStyle(2, 0xaa0000);
graphics.strokeRectShape(intersection);

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

Сборка конфигурации игры

Код завершается стандартной для Phaser конфигурацией игры. Мы указываем размеры холста, тип рендерера (Phaser.AUTO), ID родительского элемента и класс нашей сцены Example.

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

Эта конфигурация запускает игровой цикл. Важно, что метод create() сцены вызывается автоматически после инициализации игры, и все наши логика создания объектов и подписки на события выполняется один раз в начале.

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

Метод GetRectangleIntersection() — мощный и простой способ получить точную область пересечения двух прямоугольников. Вы можете использовать его не только для визуализации, но и в игровой логике: например, для расчета урона в определенной зоне, активации ловушек или определения видимости для NPC. Попробуйте поэкспериментировать: измените код так, чтобы при пересечении менялся цвет фона сцены, или добавьте третий прямоугольник для поиска пересечения трех областей сразу.