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

Создание динамических локаций, разброс предметов или случайное появление врагов — частые задачи в геймдеве. Ручной расчёт координат в заданной области отнимает время и может привести к ошибкам. Phaser предоставляет готовое решение через геометрический модуль. В этой статье разберём, как использовать `Phaser.Geom.Rectangle.getRandomPoint()` для генерации случайных позиций внутри прямоугольной зоны. Этот метод идеально подходит для расстановки ресурсов, точек возрождения или визуальных эффектов в определённых границах.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    index = 0;
    points;
    graphics;
    rect;

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

        this.rect = new Phaser.Geom.Rectangle(250, 200, 300, 200);

        this.points = [];

        for (let i = 0; i < 25; i++)
        {
            // if we omit a parameter, new Point instance will be created and returned
            this.points.push(this.rect.getRandomPoint());
        }
    }

    update ()
    {
        this.index = ++this.index % 25;

        // we can also supply an instance of Point that will be modified
        this.rect.getRandomPoint(this.points[this.index]);

        this.graphics.clear();
        this.graphics.strokeRectShape(this.rect);

        for (let i = 0; i < 25; i++)
        {
            const p = this.points[i];
            this.graphics.fillCircle(p.x, p.y, 4);
        }
    }
}

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

const game = new Phaser.Game(config);

Создание геометрической области и массива точек

В начале работы нам нужно определить прямоугольную область, внутри которой будут генерироваться точки. Для этого создаём экземпляр Phaser.Geom.Rectangle. Также подготовим массив для хранения сгенерированных точек и объект Graphics для их отрисовки.

this.graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x0000ff }, fillStyle: { color: 0xff0000 }});
this.rect = new Phaser.Geom.Rectangle(250, 200, 300, 200);
this.points = [];

Генерация точек: два варианта использования метода

Метод getRandomPoint() может работать в двух режимах. Если вызвать его без аргументов, он вернёт новый экземпляр Phaser.Geom.Point со случайными координатами внутри прямоугольника. Это удобно для первоначального заполнения массива.

for (let i = 0; i < 25; i++) {
    this.points.push(this.rect.getRandomPoint());
}

Если же передать в метод существующий объект Point, он не создаёт новый объект, а модифицирует координаты переданного. Это эффективно с точки зрения производительности, так как избегает лишних созданий объектов в цикле update.

this.rect.getRandomPoint(this.points[this.index]);

Динамическое обновление и отрисовка

В методе update мы поочерёдно обновляем одну из точек, используя второй вариант вызова getRandomPoint(). Это создаёт эффект "мерцания" или постоянного перемещения точек. После обновления данных необходимо очистить холст Graphics и перерисовать прямоугольник и все точки.

update() {
    this.index = ++this.index % 25;
    this.rect.getRandomPoint(this.points[this.index]);

    this.graphics.clear();
    this.graphics.strokeRectShape(this.rect);

    for (let i = 0; i < 25; i++) {
        const p = this.points[i];
        this.graphics.fillCircle(p.x, p.y, 4);
    }
}

Практическое применение в играх

Эта техника выходит за рамки визуального примера. Рассмотрим несколько практических сценариев:

* **Спавн предметов:** Задайте зону (Rectangle) на карте, где могут появляться аптечки или патроны. * **Появление врагов:** Определите прямоугольную область за пределами экрана, откуда будут вылетать вражеские корабли. * **Визуальные эффекты:** Создайте дождь или звёздное поле в пределах интерфейса или части игрового мира.

Ключевое преимущество — контроль. Вы точно знаете, что все объекты появятся строго внутри заданных границ, без риска выхода за пределы игровой логики.

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

Использование Phaser.Geom.Rectangle.getRandomPoint() — это мощный и производительный способ заполнения игровых областей случайным контентом. Для экспериментов попробуйте привязать прямоугольник к спрайту, чтобы зона спавна двигалась вместе с персонажем, или используйте несколько прямоугольников для создания сложных зон появления, комбинируя их результаты. Также можно поэкспериментировать с другими геометрическими фигурами из модуля Phaser.Geom, у которых есть аналогичные методы.