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

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

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

Живой запуск

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

Исходный код


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

        const triangle = Phaser.Geom.Triangle.BuildEquilateral(100, 225, 150);

        for (let angle = 0; triangle.left < 800; angle += Math.PI / 18)
        {

            graphics.strokeTriangleShape(triangle);

            Phaser.Geom.Triangle.Offset(triangle, 20, Math.cos(angle) * 40);
        }
    }
}

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

const game = new Phaser.Game(config);

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

Вся работа происходит в методе create() сцены. Первым делом мы создаем объект Graphics для отрисовки линий и определяем исходный треугольник.

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

Здесь мы инициализируем контекст рисования (graphics), задав стиль линии: толщину 2 пикселя и золотистый цвет (0xaaaa00).

const triangle = Phaser.Geom.Triangle.BuildEquilateral(100, 225, 150);

С помощью статического метода Phaser.Geom.Triangle.BuildEquilateral создается равносторонний треугольник. Параметры: координата X вершины (100), координата Y вершины (225) и длина стороны (150). Этот треугольник станет нашим «кирпичиком» для анимации.

Магия метода Offset: как работает смещение

Ключевой инструмент — метод Phaser.Geom.Triangle.Offset. Он не рисует, а модифицирует координаты существующего треугольника, сдвигая каждую его точку.

Phaser.Geom.Triangle.Offset(triangle, 20, Math.cos(angle) * 40);

Метод принимает три аргумента: сам объект треугольника, смещение по оси X и смещение по оси Y. Важно понимать, что он изменяет переданный объект triangle на месте, а не создает новый. В нашем примере смещение по X постоянно — 20 пикселей за шаг, а по Y рассчитывается динамически через косинус угла, что и создает волнообразный эффект.

Цикл анимации: отрисовка и движение

Анимация реализована в цикле for. Условие выхода — левая граница треугольника (triangle.left) не достигнет правого края холста (800 пикселей).

for (let angle = 0; triangle.left < 800; angle += Math.PI / 18)
{
    graphics.strokeTriangleShape(triangle);
    Phaser.Geom.Triangle.Offset(triangle, 20, Math.cos(angle) * 40);
}

На каждом шаге цикла происходят две операции: 1. **Отрисовка текущего положения:** graphics.strokeTriangleShape(triangle) рисует контур треугольника в его текущих координатах. 2. **Расчет нового положения:** Вызов Offset сдвигает треугольник для следующей итерации. Угол angle увеличивается на Math.PI / 18 (10 градусов), что меняет аргумент косинуса и, соответственно, смещение по Y, создавая паттерн движения «змейкой».

Сборка и запуск игры

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

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

const game = new Phaser.Game(config);

В конфиге задается размер холста 800x600, автоматический выбор WebGL/Canvas рендерера, идентификатор HTML-контейнера и класс нашей сцены Example. После создания объекта Game Phaser автоматически инициализирует рендерер и запустит сцену, выполнив наш код анимации.

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

Метод Offset — мощный и легковесный инструмент для procedural animation. Он позволяет управлять движением фигур, напрямую манипулируя их геометрией. Поэкспериментируйте: измените формулу для смещения по Y на Math.sin(angle) * 30, чтобы получить классическую синусоиду. Или примените Offset не в цикле, а в методе update(), сдвигая один треугольник по нажатию клавиши, чтобы создать контролируемого игроком «следящего» объекта. Попробуйте использовать Phaser.Geom.Triangle.Rotate внутри цикла вместе с Offset для создания спиралевидных траекторий.