О чем этот пример
Создание случайных точек внутри ограниченной области — частая задача в разработке игр, будь то спавн предметов, расположение врагов или генерация частиц. В Phaser для этого есть удобный инструмент — класс `Phaser.Geom.Ellipse`. В этой статье мы разберем, как работает его метод `getRandomPoint()`, и покажем, как его эффективно использовать для динамической визуализации.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
index = 0;
points;
graphics;
ellipse;
create ()
{
this.ellipse = new Phaser.Geom.Ellipse(400, 300, 400, 250);
this.graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x00aaaa }, fillStyle: { color: 0xff0000 }});
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.ellipse.getRandomPoint());
}
}
update ()
{
this.index = ++this.index % 25;
// we can also supply an instance of Point that will be modified
this.ellipse.getRandomPoint(this.points[this.index]);
this.graphics.clear();
this.graphics.strokeEllipseShape(this.ellipse);
for (let i = 0; i < 25; i++)
{
const p = this.points[i];
this.graphics.fillRect(p.x - 4, p.y - 4, 8, 8);
}
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Создание эллипса и подготовка данных
В начале сцены мы создаем геометрический объект эллипса. Его конструктор принимает координаты центра (x, y), ширину и высоту. Мы также инициализируем массив для хранения точек и объект Graphics для их отрисовки.
this.ellipse = new Phaser.Geom.Ellipse(400, 300, 400, 250);
this.graphics = this.add.graphics({ lineStyle: { width: 2, color: 0x00aaaa }, fillStyle: { color: 0xff0000 }});
this.points = [];
Получение случайных точек: две стратегии
Метод getRandomPoint() класса Phaser.Geom.Ellipse можно использовать двумя способами, что демонстрирует основную логику работы.
Первый способ — вызов без аргументов. Метод создает и возвращает новый экземпляр Phaser.Geom.Point. Это удобно для первоначального заполнения массива.
// Создается новый объект Point
this.points.push(this.ellipse.getRandomPoint());
Второй способ — передача существующего объекта Point в качестве аргумента. В этом случае метод не создает новый объект, а модифицирует координаты переданного. Это экономит ресурсы, избегая лишних созданий объектов в цикле update.
// Передаем существующую точку, её координаты будут обновлены
this.ellipse.getRandomPoint(this.points[this.index]);
Динамическое обновление и отрисовка
В методе update() мы поочередно обновляем каждую точку в массиве, используя второй, оптимизированный способ. После этого полностью очищаем холст Graphics и заново рисуем контур эллипса и все точки в виде маленьких квадратов.
update ()
{
// Циклически меняем индекс точки для обновления
this.index = ++this.index % 25;
this.ellipse.getRandomPoint(this.points[this.index]);
this.graphics.clear();
this.graphics.strokeEllipseShape(this.ellipse);
for (let i = 0; i < 25; i++)
{
const p = this.points[i];
this.graphics.fillRect(p.x - 4, p.y - 4, 8, 8);
}
}
Именно такой подход — обновление одной точки за кадр — создает плавную анимацию, когда точки "дёргаются" на своих местах, но не требует пересчёта всех 25 позиций каждый раз.
Сборка сцены и конфигурация игры
Финальный шаг — стандартная конфигурация игры Phaser. Мы указываем размеры холста, тип рендерера и класс нашей сцены.
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Метод getRandomPoint() — это мощный и гибкий инструмент для работы со случайными позициями внутри эллипса. Оптимизация через переиспользование объектов Point критически важна для поддержания высокой частоты кадров. Для экспериментов попробуйте изменить форму на Phaser.Geom.Rectangle (у него тоже есть getRandomPoint), добавить физические тела в вычисленные точки или реализовать генерацию точек внутри сложной фигуры, составленной из нескольких эллипсов.
