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

Точное позиционирование объектов — одна из ключевых задач в разработке игр. Метод `Phaser.Geom.Rectangle.GetCenter()` предоставляет простой и эффективный способ вычисления центральной точки любого прямоугольника в вашей сцене. В этой статье мы разберем практический пример, который демонстрирует, как использовать этот метод для динамического обновления и визуализации центров множества прямоугольников. Это знание пригодится для привязки спрайтов, UI-элементов или областей взаимодействия к геометрическим формам.

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

Живой запуск

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

Исходный код


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

        const rectangles = [];
        const points = [];

        for (let x = 0; x < 10; x++)
        {
            for (let y = 0; y < 10; y++)
            {
                const width = Phaser.Math.Between(20, 80);
                const height = Phaser.Math.Between(15, 60);

                const rect = new Phaser.Geom.Rectangle(x * 80, y * 60, width, height);

                rectangles.push(rect);

                points.push(Phaser.Geom.Rectangle.GetCenter(rect));
            }
        }

        redraw();

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

            recalculate();

            redraw();

        });

        function recalculate ()
        {
            for (let i = 0; i < rectangles.length; i++)
            {
                const width = Phaser.Math.Between(20, 80);
                const height = Phaser.Math.Between(15, 60);

                rectangles[i].setSize(width, height);

                Phaser.Geom.Rectangle.GetCenter(rectangles[i], points[i]);
            }
        }

        function redraw ()
        {
            graphics.clear();

            graphics.lineStyle(2, 0x0000aa);

            for (let i = 0; i < rectangles.length; i++)
            {
                const rect = rectangles[i];

                graphics.strokeRectShape(rect);

                Phaser.Geom.Rectangle.GetCenter(rect, points[i]);

                graphics.fillPointShape(points[i], 5);
            }

            graphics.lineStyle(1, 0x00aa00);

            graphics.strokePoints(points);
        }
    }
}

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

const game = new Phaser.Game(config);

Инициализация сцены и создание объектов

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

const graphics = this.add.graphics({ fillStyle: { color: 0x00aa00 }, lineStyle: { color: 0x0000aa } });

Затем объявляются два массива: rectangles для хранения объектов прямоугольников и points для хранения их центральных точек. Это позволяет нам управлять множеством объектов независимо.

Создание сетки прямоугольников и их центров

Используя вложенный цикл, мы генерируем сетку из 100 прямоугольников. Для каждого из них случайным образом задаются ширина и высота с помощью Phaser.Math.Between. Каждый новый прямоугольник создается как экземпляр Phaser.Geom.Rectangle.

const width = Phaser.Math.Between(20, 80);
const height = Phaser.Math.Between(15, 60);
const rect = new Phaser.Geom.Rectangle(x * 80, y * 60, width, height);
rectangles.push(rect);

Сразу после создания прямоугольника вычисляется и сохраняется его центральная точка. Статический метод Phaser.Geom.Rectangle.GetCenter() принимает прямоугольник в качестве аргумента и возвращает объект точки Phaser.Geom.Point.

points.push(Phaser.Geom.Rectangle.GetCenter(rect));

После заполнения массивов вызывается функция redraw() для их первоначальной отрисовки.

Динамическое обновление по клику

Пример становится интерактивным благодаря обработчику события pointerdown. При каждом клике мыши вызывается функция recalculate(), которая изменяет размеры всех прямоугольников и заново вычисляет их центры.

this.input.on('pointerdown', pointer => {
    recalculate();
    redraw();
});

Внутри recalculate() для каждого прямоугольника генерируются новые случайные размеры. Важный момент: метод setSize() изменяет ширину и высоту существующего прямоугольника, сохраняя его исходную позицию (координаты x, y левого верхнего угла).

rectangles[i].setSize(width, height);

Затем мы снова используем GetCenter(), но в его второй, перегруженной форме. Первым аргументом передается прямоугольник, а вторым — объект точки, в который нужно записать результат. Это позволяет перезаписать значение в существующем объекте из массива points, избегая создания новых объектов и утечек памяти.

Phaser.Geom.Rectangle.GetCenter(rectangles[i], points[i]);

Визуализация: Отрисовка и перерисовка

Функция redraw() отвечает за отображение состояния на экране. Она начинается с очистки холста graphics.clear().

Сначала рисуются контуры всех прямоугольников с помощью graphics.strokeRectShape().

graphics.strokeRectShape(rect);

Затем для каждой пары прямоугольник-точка вычисляется центр (здесь вызов дублируется для наглядности в исходнике) и рисуется закрашенная точка в этой позиции.

graphics.fillPointShape(points[i], 5);

Наконец, все центральные точки соединяются одной ломаной линией зеленого цвета, что создает интересный визуальный эффект сетки.

graphics.strokePoints(points);

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

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

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