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

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

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    points;
    triangles;
    graphics;

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

        this.triangles = [
            Phaser.Geom.Triangle.BuildRight(175, 450, 50, 250),
            Phaser.Geom.Triangle.BuildRight(375, 450, 50, 250),
            Phaser.Geom.Triangle.BuildRight(575, 450, 50, 250),
            Phaser.Geom.Triangle.BuildEquilateral(400, 70, 50),
            Phaser.Geom.Triangle.BuildEquilateral(400, 70, 50),
            Phaser.Geom.Triangle.BuildEquilateral(400, 70, 50)
        ];

        this.points = [
            Phaser.Geom.Triangle.Centroid(this.triangles[0]),
            Phaser.Geom.Triangle.CircumCenter(this.triangles[1]),
            Phaser.Geom.Triangle.InCenter(this.triangles[2])
        ];

        Phaser.Geom.Triangle.Decompose(this.triangles[3], this.points);

    }

    update ()
    {

        this.graphics.clear();

        for (let i = 0; i < this.triangles.length; i++)
        {
            Phaser.Geom.Triangle.RotateAroundPoint(this.triangles[i], this.points[i], 0.02);

            this.graphics.strokeTriangleShape(this.triangles[i]);

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

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

const game = new Phaser.Game(config);

Подготовка сцены и создание фигур

В методе create() инициализируются основные элементы: холст для рисования (Graphics), массив треугольников и массив точек вращения.

Сначала создается объект graphics, который будет отвечать за отрисовку контуров и заливку фигур.

this.graphics = this.add.graphics({ lineStyle: { width: 2, color: 0xaaaa00 }, fillStyle: { color: 0x0000aa } });

Затем формируется массив triangles. Первые три треугольника создаются с помощью Phaser.Geom.Triangle.BuildRight (прямоугольные), а следующие три — с помощью Phaser.Geom.Triangle.BuildEquilateral (равносторонние). Обратите внимание, что последние три треугольника созданы с одинаковыми параметрами и изначально перекрывают друг друга.

this.triangles = [
    Phaser.Geom.Triangle.BuildRight(175, 450, 50, 250),
    Phaser.Geom.Triangle.BuildRight(375, 450, 50, 250),
    Phaser.Geom.Triangle.BuildRight(575, 450, 50, 250),
    Phaser.Geom.Triangle.BuildEquilateral(400, 70, 50),
    Phaser.Geom.Triangle.BuildEquilateral(400, 70, 50),
    Phaser.Geom.Triangle.BuildEquilateral(400, 70, 50)
];

Определение точек вращения

Каждому треугольнику нужна своя точка, вокруг которой он будет вращаться. Эти точки хранятся в массиве points.

Для первых трех треугольников точки вычисляются как их геометрические центры, но все они разные: - Для треугольника с индексом 0 — это Centroid (центроид, точка пересечения медиан). - Для треугольника с индексом 1 — это CircumCenter (центр описанной окружности). - Для треугольника с индексом 2 — это InCenter (центр вписанной окружности).

this.points = [
    Phaser.Geom.Triangle.Centroid(this.triangles[0]),
    Phaser.Geom.Triangle.CircumCenter(this.triangles[1]),
    Phaser.Geom.Triangle.InCenter(this.triangles[2])
];

Для последних трех равносторонних треугольников используется хитрый прием. Метод Phaser.Geom.Triangle.Decompose разбивает треугольник (третий в массиве triangles, с индексом 3) на три точки — его вершины. Эти три точки записываются в массив points, начиная с индекса 3. Таким образом, каждый из оставшихся треугольников (с индексами 3, 4, 5) получает для вращения одну из вершин первого равностороннего треугольника.

Phaser.Geom.Triangle.Decompose(this.triangles[3], this.points);

Анимация вращения в игровом цикле

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

this.graphics.clear();

Затем в цикле для каждого треугольника выполняется ключевое действие: вращение вокруг своей точки из массива points с помощью метода Phaser.Geom.Triangle.RotateAroundPoint. Второй аргумент — точка вращения, третий — угол в радианах. Значение 0.02 обеспечивает плавное вращение.

Phaser.Geom.Triangle.RotateAroundPoint(this.triangles[i], this.points[i], 0.02);

После изменения координат треугольника он отрисовывается на холсте как контур. Точка вращения отрисовывается как закрашенный круг.

this.graphics.strokeTriangleShape(this.triangles[i]);
this.graphics.fillPointShape(this.points[i], 10);

Именно этот код в update() создает впечатление непрерывного вращения треугольников вокруг своих осей.

Конфигурация и запуск игры

Пример завершается стандартной для Phaser 3 конфигурацией игры. В объекте config задаются размеры холста, тип рендерера, родительский элемент в DOM и стартовая сцена.

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

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

const game = new Phaser.Game(config);

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

Метод Phaser.Geom.Triangle.RotateAroundPoint — это мощный и простой инструмент для преобразования геометрии. Вы можете вращать не только треугольники, но и любые другие фигуры, если представите их как набор вершин. Для экспериментов попробуйте: 1. Изменить скорость вращения для разных треугольников, чтобы создать более сложную анимацию. 2. Заставить точку вращения двигаться по экрану — треугольник будет описывать вокруг неё круги. 3. Привязать точку вращения к позиции другого игрового объекта (например, спрайта), создав эффект спутника.