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

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

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

Живой запуск

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

Исходный код


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

        const pointerTriangle = new Phaser.Geom.Triangle.BuildEquilateral(100, 100, 150);

        const triangles = [];

        for (let k = 0; k < 45; k++)
        {
            triangles.push(new Phaser.Geom.Triangle());
        }

        let i = 0;

        this.input.on('pointermove', pointer =>
        {

            Phaser.Geom.Triangle.CenterOn(pointerTriangle, pointer.x, pointer.y);

            Phaser.Geom.Triangle.CopyFrom(pointerTriangle, triangles[i]);

            i = (i + 1) % triangles.length;

            graphics.clear();

            graphics.strokeTriangleShape(pointerTriangle);

            for (let j = 0; j < triangles.length; j++)
            {
                Phaser.Geom.Triangle.Rotate(triangles[j], 0.15);

                graphics.strokeTriangleShape(triangles[j]);
            }
        });
    }
}

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

const game = new Phaser.Game(config);

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

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

Затем определяется главный треугольник pointerTriangle. Он создается как равносторонний с центром в точке (100, 100) и длиной стороны 150 пикселей. Этот треугольник будет следовать за курсором.

Также создается пустой массив triangles, который будет хранить копии основного треугольника для анимации. В цикле в него помещается 45 новых пустых объектов Phaser.Geom.Triangle.

const graphics = this.add.graphics({ lineStyle: { width: 3, color: 0xaaaa00 } });
const pointerTriangle = new Phaser.Geom.Triangle.BuildEquilateral(100, 100, 150);
const triangles = [];
for (let k = 0; k < 45; k++) {
    triangles.push(new Phaser.Geom.Triangle());
}

Обработка движения курсора и копирование геометрии

Для отслеживания движения курсора используется событие 'pointermove'. При каждом движении мыши выполняются ключевые операции по обновлению позиций треугольников.

Сначала метод Phaser.Geom.Triangle.CenterOn() перемещает pointerTriangle так, чтобы его центр совпал с текущими координатами курсора (pointer.x, pointer.y).

Затем с помощью Phaser.Geom.Triangle.CopyFrom() текущее состояние pointerTriangle копируется в один из треугольников массива triangles. Индекс `i` указывает, в какой элемент массива будет выполнено копирование. После каждой операции индекс обновляется по модулю длины массива, обеспечивая циклическую перезапись старых треугольников новыми данными.

Phaser.Geom.Triangle.CenterOn(pointerTriangle, pointer.x, pointer.y);
Phaser.Geom.Triangle.CopyFrom(pointerTriangle, triangles[i]);
i = (i + 1) % triangles.length;

Очистка, вращение и отрисовка треугольников

После обновления данных необходимо перерисовать всю сцену. Сначала вызывается graphics.clear(), чтобы стереть все, что было нарисовано в предыдущем кадре.

Затем отрисовывается главный треугольник, следующий за курсором, с помощью graphics.strokeTriangleShape(pointerTriangle).

Далее в цикле обрабатывается каждый треугольник из массива triangles. Метод Phaser.Geom.Triangle.Rotate() применяется к каждому треугольнику, увеличивая его угол поворота на 0.15 радиана. Это создает эффект постепенного вращения всех следов. После вращения каждый треугольник также отрисовывается.

graphics.clear();
graphics.strokeTriangleShape(pointerTriangle);
for (let j = 0; j < triangles.length; j++) {
    Phaser.Geom.Triangle.Rotate(triangles[j], 0.15);
    graphics.strokeTriangleShape(triangles[j]);
}

Настройка игры и запуск

Конфигурационный объект config определяет основные параметры игры: размеры холста, тип рендерера (Phaser.AUTO), родительский HTML-элемент и главную сцену Example. Создание экземпляра Phaser.Game с этой конфигурацией запускает приложение.

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

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

Этот пример наглядно показывает, как с помощью нескольких методов Phaser.Geom.Triangle можно создать сложную визуальную анимацию. Для экспериментов попробуйте изменить количество треугольников в массиве, скорость вращения (0.15), стиль линий в graphics или замените Triangle.BuildEquilateral на другую форму, например Triangle.BuildRight. Также можно добавить изменение цвета или прозрачности треугольников в зависимости от их возраста в массиве, создавая эффект шлейфа.