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

Работа с геометрией — важная часть разработки игр. Например, вам может понадобиться равномерно разместить объекты вдоль границы фигуры для создания патрулей, эффектов или UI-элементов. В Phaser для этого есть удобный метод `getPoints()` у геометрического объекта `Triangle`. В этой статье мы разберем, как им пользоваться, какие параметры он принимает и как визуализировать результат.

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

Живой запуск

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

Исходный код


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

        // triangle = new Phaser.Geom.Triangle.BuildEquilateral(400, 200, 300);

        // triangle = new Phaser.Geom.Triangle.BuildRight(200, 400, 300, 200);

        //  Random
        const x1 = Phaser.Math.Between(50, 400);
        const y1 = Phaser.Math.Between(50, 300);

        const x2 = Phaser.Math.Between(450, 750);
        const y2 = Phaser.Math.Between(50, 300);

        const x3 = Phaser.Math.Between(50, 750);
        const y3 = Phaser.Math.Between(350, 550);

        const triangle = new Phaser.Geom.Triangle(x1, y1, x2, y2, x3, y3);

        graphics.strokeTriangleShape(triangle);

        //  Get 64 points around the triangle
        const points = triangle.getPoints(32);

        //  Every point will be 50px apart (note the 'false' given for the quantity argument)
        //  If the stepRate doesn't divide equally into the triangle dimensions then you'll get offset values at the end
        // var points = triangle.getPoints(false, 50);

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

Создаем произвольный треугольник

Перед тем как получать точки, нужен сам треугольник. В примере используется конструктор Phaser.Geom.Triangle, принимающий координаты трех вершин.

const x1 = Phaser.Math.Between(50, 400);
const y1 = Phaser.Math.Between(50, 300);
const x2 = Phaser.Math.Between(450, 750);
const y2 = Phaser.Math.Between(50, 300);
const x3 = Phaser.Math.Between(50, 750);
const y3 = Phaser.Math.Between(350, 550);

const triangle = new Phaser.Geom.Triangle(x1, y1, x2, y2, x3, y3);

Для наглядности мы рисуем контур треугольника с помощью графического объекта Graphics и метода strokeTriangleShape().

Метод `getPoints()`: количество точек или шаг

Ключевой метод статьи — triangle.getPoints(). Он может работать в двух режимах, в зависимости от переданных аргументов.

**Первый режим:** Указываем количество точек на *каждой* стороне треугольника. Метод равномерно распределит их по периметру. В примере запрашивается 32 точки на сторону, но итоговое количество будет 64. Почему? Потому что каждая вершина принадлежит двум сторонам и метод, чтобы избежать дублирования точек в углах, возвращает массив, где общие вершины не повторяются.

// Получить 32 точки на каждую сторону (итого ~64 точки по периметру)
const points = triangle.getPoints(32);

**Второй режим:** Указываем шаг в пикселях между точками. Для этого первым аргументом передаем false, а вторым — желаемое расстояние.

// Получить точки, расположенные с шагом в 50 пикселей вдоль сторон
const points = triangle.getPoints(false, 50);

Важно: если длина стороны не кратна шагу, последняя точка на стороне может не совпасть с вершиной, что приведет к небольшому смещению интервала.

Визуализация результата

Метод getPoints() возвращает массив объектов с координатами `xиy`. Чтобы увидеть, где именно расположены точки, мы можем их нарисовать.

В примере используется цикл, который проходит по всем точкам и рисует в их координатах маленькие квадратики с помощью graphics.fillRect(). Центр квадрата смещается на половину его ширины и высоты, чтобы точка оказалась ровно посередине фигуры.

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

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

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

Зачем это может пригодиться? Вот несколько идей: * **Маршрут патруля:** Создать путь для NPC, который ходит вдоль треугольной зоны. * **Размещение объектов:** Равномерно расставить декорации (фонари, камни) вдоль границы области. * **Эффекты частиц:** Запустить частицы не из одной точки, а вдоль всей линии, например, для эффекта "энергетического щита". * **Построение сетки или зоны:** Использовать точки как опорные для более сложных расчетов или отрисовки.

Метод работает не только с Triangle, но и с другими геометрическими объектами Phaser, такими как Line, Rectangle и Circle, что делает его универсальным инструментом.

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

Метод getPoints() геометрического объекта Triangle — это мощный и гибкий инструмент для получения координат вдоль периметра фигуры. Вы можете контролировать детализацию, задавая либо точное количество точек на сторону, либо фиксированное расстояние между ними. Поэкспериментируйте: попробуйте анимировать полученные точки, создав вдоль них движение спрайтов, или скомбинируйте несколько треугольников для построения сложного пути.