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

Работа с геометрией — важная часть игровой разработки, будь то расчёт траекторий, генерация уровней или создание визуальных эффектов. Класс `Phaser.Geom.Polygon` предоставляет мощные инструменты для манипуляций с многоугольниками. В этой статье мы разберём практическое применение метода `getPoints`, который позволяет дискретизировать контур полигона — получить массив точек, равномерно распределённых по его периметру. Этот подход полезен для точечной отрисовки контура, создания цепочек частиц вдоль фигуры или для последующего физического моделирования.

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

Живой запуск

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

Исходный код


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

        const polygon = new Phaser.Geom.Polygon([
            400, 100,
            200, 278,
            340, 430,
            650, 80
        ]);

        const points = polygon.getPoints(32);

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

            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);

Что делает метод getPoints?

Метод getPoints(quantity) объекта Phaser.Geom.Polygon выполняет простую, но полезную задачу: он возвращает массив объектов Phaser.Geom.Point. Каждая точка лежит на периметре полигона. Ключевая особенность — точки распределяются равномерно по всей длине контура, а не просто по вершинам. Это позволяет работать с полигоном как с плавной линией.

Аргумент quantity определяет, сколько точек мы хотим получить. Чем больше значение, тем выше «разрешение» контура — точки будут расположены ближе друг к другу. В исходном примере используется значение 32, что даёт достаточно детализированное представление формы.

Разбор примера: создание и визуализация

Рассмотрим код по порядку. Сначала создаётся полигон с четырьмя вершинами. Координаты передаются в конструктор простым плоским массивом в формате [x1, y1, x2, y2, ...].

const polygon = new Phaser.Geom.Polygon([
    400, 100,
    200, 278,
    340, 430,
    650, 80
]);

Далее вызывается целевой метод для получения 32 точек по периметру.

const points = polygon.getPoints(32);

Теперь в переменной points лежит массив из 32 объектов. Каждый объект имеет свойства `xиy. Чтобы их увидеть, пример последовательно рисует в каждой позиции маленький квадратик с помощью графики (Graphics`).

for (let i = 0; i < points.length; i++)
{
    const p = points[i];
    graphics.fillRect(p.x - 4, p.y - 4, 8, 8);
}

Обратите внимание на смещение на -4: метод fillRect рисует прямоугольник от указанной координаты, поэтому мы сдвигаем точку влево-вверх на половину размера квадрата (8/2=4), чтобы точка оказалась в его центре.

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

Зачем может понадобиться такой массив точек в реальном проекте? Вот несколько идей:

* **Траектории и патрулирование:** Полученные точки можно использовать как узлы пути для NPC или снаряда, движущегося вдоль сложной формы. * **Визуальные эффекты:** На каждой точке можно создать частицу (Particle) или спрайт, создав эффект свечения, электрического разряда или пунктирного контура. * **Коллайдеры для сложных форм:** Хотя для физики обычно используют более специализированные методы, массив точек может стать основой для построения пользовательского контура столкновений. * **Генерация контента:** Равномерно распределённые точки подходят для расстановки декораций (камней, растений) вдоль заранее заданной границы области.

Важно: метод возвращает точки именно на периметре, а не внутри полигона. Для заполнения внутренности потребуются другие подходы, например, Phaser.Geom.Polygon.GetPoints с иным алгоритмом.

Влияние количества точек на результат

Давайте поэкспериментируем с аргументом quantity. Разное количество точек кардинально меняет результат.

// Мало точек — видна грубая структура периметра
const sparsePoints = polygon.getPoints(8);

// Много точек — контур выглядит почти сплошным
const densePoints = polygon.getPoints(128);

При малом количестве (например, 4-8) точки будут стоять в основном на длинных рёбрах, и форма может читаться плохо. При большом количестве (64-128) квадратики начнут сливаться, формируя почти непрерывную линию. Оптимальное значение зависит от задачи: для расстановки объектов хватит и 20-30, для плавной визуализации — больше 50.

Попробуйте в примере заменить число 32 на 8 или 64 и увидите разницу.

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

Метод getPoints — это ваш инструмент для превращения статичного полигона в динамичный набор координат, готовый к использованию в игровой логике. Он стирает грань между векторной формой и дискретными данными, открывая возможности для визуализации и симуляции. **Идеи для экспериментов:** 1. Сделайте анимацию: перемещайте спрайт от одной полученной точки к следующей, создав движение по контуру. 2. Соедините точки не квадратами, а линиями, используя graphics.lineBetween, и сравните с прямой отрисовкой полигона. 3. Сгенерируйте полигон случайной формы и примените getPoints к нему, чтобы создать непредсказуемый патрульный путь.