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

При разработке игр часто требуется проверять взаимное расположение геометрических фигур. Например, находится ли игрок (прямоугольник) в безопасной зоне (круг) или вышел ли он за её пределы? Phaser предоставляет удобные методы для таких проверок. В этой статье разберем, как использовать `Phaser.Geom.Circle.ContainsRect()` для определения полного нахождения прямоугольника внутри круга. Этот подход эффективнее ручных расчетов и подходит для проверки зон, триггеров и ограничивающих областей.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    a = 0;
    graphics;
    rect;
    circle;

    create ()
    {
        this.graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x00ff00 }, fillStyle: { color: 0xff0000 }});

        this.circle = new Phaser.Geom.Circle(400, 300, 250);
        this.rect = new Phaser.Geom.Rectangle(0, 0, 100, 100);
    }

    update ()
    {
        this.a += 0.01;

        if (this.a > Math.PI * 2)
        {
            this.a -= Math.PI * 2;
        }

        this.rect.x = 350 - Math.sin(this.a * 2) * 350;
        this.rect.y = 250 - Math.cos(this.a) * 250;

        this.graphics.clear();
        this.graphics.strokeCircleShape(this.circle);

        if (Phaser.Geom.Circle.ContainsRect(this.circle, this.rect))
        {
            this.graphics.fillStyle(0xff0000);
        }
        else
        {
            this.graphics.fillStyle(0x0000ff);
        }

        this.graphics.fillRectShape(this.rect);
    }
}

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

const game = new Phaser.Game(config);

Подготовка сцены и создание фигур

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

create ()
{
    this.graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x00ff00 }, fillStyle: { color: 0xff0000 }});

    this.circle = new Phaser.Geom.Circle(400, 300, 250);
    this.rect = new Phaser.Geom.Rectangle(0, 0, 100, 100);
}

Объект this.graphics — это инструмент для рисования. Мы задаем ему стиль линии (зеленая, толщиной 2 пикселя) и стиль заливки (красный).

Круг создается с центром в точке (400, 300) и радиусом 250 пикселей. Прямоугольник — с началом в (0, 0), шириной и высотой по 100 пикселей. Его положение будет динамически меняться в update().

Анимация движения прямоугольника

В методе update() реализуется циклическая анимация движения прямоугольника по сложной траектории.

update ()
{
    this.a += 0.01;

    if (this.a > Math.PI * 2)
    {
        this.a -= Math.PI * 2;
    }

    this.rect.x = 350 - Math.sin(this.a * 2) * 350;
    this.rect.y = 250 - Math.cos(this.a) * 250;
}

Переменная this.a — это угол, увеличивающийся каждый кадр. Условие сбрасывает его значение после полного оборота (2π), чтобы избежать переполнения.

Координаты прямоугольника вычисляются с помощью тригонометрических функций sin и cos. Умножение угла на разные коэффициенты (this.a * 2 для X и просто this.a для Y) создает интересную траекторию движения — прямоугольник движется по сложной петле, а не по простому кругу.

Отрисовка и ключевая проверка

Перед каждой отрисовкой нужно очистить холст Graphics и проверить текущее положение фигур.

this.graphics.clear();
this.graphics.strokeCircleShape(this.circle);

if (Phaser.Geom.Circle.ContainsRect(this.circle, this.rect))
{
    this.graphics.fillStyle(0xff0000);
}
else
{
    this.graphics.fillStyle(0x0000ff);
}

this.graphics.fillRectShape(this.rect);

Метод clear() удаляет все, что было нарисовано на this.graphics в предыдущем кадре. Затем контур круга отрисовывается с помощью strokeCircleShape().

Далее происходит главное: вызов Phaser.Geom.Circle.ContainsRect(this.circle, this.rect). Этот статический метод возвращает true, только если прямоугольник **целиком** находится внутри круга, включая его границы. Если хотя бы один угол выходит за пределы круга — вернется false.

В зависимости от результата меняется цвет заливки fillStyle(): красный (0xff0000) для прямоугольника внутри круга и синий (0x0000ff) для вышедшего за его пределы. После установки цвета прямоугольник рисуется методом fillRectShape().

Настройка игры и конфигурация

Запуск игры осуществляется через создание экземпляра Phaser.Game с конфигурационным объектом.

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

const game = new Phaser.Game(config);

Объект config определяет основные параметры игры: ширину и высоту холста (800x600), способ рендеринга (Phaser.AUTO выбирает между WebGL и Canvas автоматически), ID HTML-элемента, в который будет встроена игра, и нашу сцену Example.

Создание new Phaser.Game(config) инициализирует игровой цикл, который начинает вызывать методы create() (один раз) и update() (каждый кадр).

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

Метод Phaser.Geom.Circle.ContainsRect() — это надежный и производительный способ проверки полного вхождения прямоугольной области в круглую. Он избавляет от необходимости писать собственные геометрические расчеты. Для экспериментов попробуйте изменить размеры или форму фигур, добавить несколько прямоугольников или кругов, либо использовать другую проверку — Phaser.Geom.Circle.Contains() — для определения нахождения точки внутри круга. Это может быть полезно для реализации зон обнаружения для врагов или безопасных зон для восстановления здоровья игрока.