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

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

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    constructor ()
    {
        super();
    }

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.spritesheet('diamonds', 'assets/sprites/diamonds32x24x5.png', { frameWidth: 32, frameHeight: 24 });
    }

    create ()
    {
        this.group = this.add.group();

        for (var i = 0; i < 256; i++)
        {
            this.group.create(Phaser.Math.Between(200, 600), Phaser.Math.Between(100, 500), 'diamonds', Phaser.Math.Between(0, 4));
        }
    }

    update ()
    {
        Phaser.Actions.RotateAround(this.group.getChildren(), { x: 400, y: 300 }, 0.01);
    }
}

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

const game = new Phaser.Game(config);

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

В методе preload мы загружаем спрайтшит — изображение, содержащее несколько кадров (спрайтов) в одной текстуре. Это эффективно для отрисовки множества одинаковых объектов с небольшими вариациями.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.spritesheet('diamonds', 'assets/sprites/diamonds32x24x5.png', { frameWidth: 32, frameHeight: 24 });
}

Здесь setBaseURL задаёт базовый путь для загрузки. Метод load.spritesheet загружает изображение diamonds32x24x5.png и разрезает его на кадры размером 32x24 пикселя. Последний параметр { frameWidth: 32, frameHeight: 24 } — это конфигурация для нарезки.

Создание группы и наполнение её объектами

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

create ()
{
    this.group = this.add.group();

    for (var i = 0; i < 256; i++)
    {
        this.group.create(Phaser.Math.Between(200, 600), Phaser.Math.Between(100, 500), 'diamonds', Phaser.Math.Between(0, 4));
    }
}

Цикл создаёт 256 спрайтов внутри группы. Метод this.group.create добавляет новый спрайт в группу. Его параметры: 1. X-координата, сгенерированная случайно между 200 и 600. 2. Y-координата, сгенерированная случайно между 100 и 500. 3. Ключ текстуры 'diamonds'. 4. Индекс кадра из спрайтшита (от 0 до 4), также выбранный случайно. Это позволяет каждому алмазу иметь один из пяти возможных цветов.

Функции Phaser.Math.Between обеспечивают случайное начальное размещение объектов по экрану.

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

Сердце примера — метод update, который вызывается на каждом кадре игры. Именно здесь применяется действие RotateAround.

update ()
{
    Phaser.Actions.RotateAround(this.group.getChildren(), { x: 400, y: 300 }, 0.01);
}
Метод `Phaser.Actions.RotateAround` принимает три аргумента:
1.  Массив объектов для вращения. Мы получаем его через `this.group.getChildren()`.
2.  Точка вращения в виде объекта с координатами `{ x: 400, y: 300 }`. Это центр условной окружности.
3.  Угол поворота в радианах за один вызов (за один кадр). Значение `0.01` обеспечивает плавное, медленное вращение.

На каждом кадре все 256 алмазов в группе немного смещаются по круговой орбите вокруг точки (400, 300). Поскольку исходные позиции алмазов случайны, они образуют не сплошное кольцо, а динамичное «роящееся» облако, вращающееся как единое целое.

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

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

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

const game = new Phaser.Game(config);

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

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

Метод Phaser.Actions.RotateAround — мощный и лаконичный инструмент для анимации групп объектов. Он избавляет разработчика от необходимости вручную рассчитывать тригонометрию для каждого спрайта. Для экспериментов попробуйте изменить скорость вращения, точку центра или комбинируйте RotateAround с другими действиями, например Phaser.Actions.Scale или Phaser.Actions.SetTint, чтобы создавать ещё более сложные и красочные визуальные эффекты, такие как пульсирующие спирали или цветовые волны.