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

Визуальные эффекты — важная часть игровой атмосферы. Одиночная анимация может выглядеть хорошо, но синхронный запуск десятков анимаций с задержкой создаёт по-настоящему впечатляющие картины. В этой статье мы разберём мощный метод `staggerPlay`, который позволяет легко управлять массовым воспроизведением анимаций, создавая сложные волновые и каскадные эффекты всего несколькими строками кода.

Версия 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.atlas('lazer', 'assets/animations/lazer/lazer.png', 'assets/animations/lazer/lazer.json');
    }

    create ()
    {
        this.anims.create({ key: 'blast', frames: this.anims.generateFrameNames('lazer', { prefix: 'lazer_', start: 0, end: 22, zeroPad: 2 }), repeat: -1 });

        var group = this.add.group();

        group.createMultiple({ key: 'lazer', frame: 'lazer_22', repeat: 39, setScale: { x: 0.25, y: 0.25 } });

        Phaser.Actions.GridAlign(group.getChildren(), {
            width: 20,
            height: 2,
            cellWidth: 32,
            cellHeight: 280,
            x: -100,
            y: -350
        });

        this.anims.staggerPlay('blast', group.getChildren(), 20);
    }
}

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

const game = new Phaser.Game(config);

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

Перед использованием staggerPlay необходимо создать анимацию и подготовить группу объектов, которые будут её воспроизводить. В примере загружается атлас lazer, из которого создаётся циклическая анимация blast.

this.anims.create({
    key: 'blast',
    frames: this.anims.generateFrameNames('lazer', {
        prefix: 'lazer_',
        start: 0,
        end: 22,
        zeroPad: 2
    }),
    repeat: -1
});

Далее создаётся группа (Group) и заполняется множеством спрайтов. Ключевой параметр setScale уменьшает спрайты, что важно для последующего выравнивания. Метод createMultiple — эффективный способ создать сразу 40 экземпляров (1 исходный + 39 повторов).

var group = this.add.group();
group.createMultiple({
    key: 'lazer',
    frame: 'lazer_22',
    repeat: 39,
    setScale: { x: 0.25, y: 0.25 }
});

Выравнивание объектов в сетку

Чтобы эффект выглядел упорядоченно, спрайты нужно расположить. Phaser.Actions.GridAlign — идеальный инструмент для размещения массива объектов по виртуальной сетке.

Phaser.Actions.GridAlign(group.getChildren(), {
    width: 20,
    height: 2,
    cellWidth: 32,
    cellHeight: 280,
    x: -100,
    y: -350
});

Параметры width и height определяют размерность сетки (20 колонок, 2 ряда). cellWidth и cellHeight задают шаг между ячейками. Параметры `xиy` — это начальная точка для размещения всей сетки на сцене. В результате 40 спрайтов выстраиваются в два длинных ряда.

Волшебство метода staggerPlay

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

this.anims.staggerPlay('blast', group.getChildren(), 20);

Метод принимает три ключевых аргумента: 1. Ключ анимации ('blast'). 2. Массив игровых объектов, которые могут её проигрывать. 3. Задержка в миллисекундах между запуском анимации на соседних объектах.

Система пройдётся по массиву объектов и запустит анимацию 'blast' на каждом из них, но не одновременно, а с указанной задержкой. Поскольку наши спрайты выровнены в сетку слева направо, создаётся эффект "бегущей волны" или последовательного залпа.

Как работает задержка и порядок

Задержка применяется линейно к порядку элементов в переданном массиве. В нашем примере массив group.getChildren() возвращает спрайты в порядке их создания. Поскольку они были созданы пачкой и затем выровнены по сетке, порядок в массиве соответствует порядку заполнения сетки: сначала первый ряд слева направо, затем второй ряд слева направо.

Задержка в 20 мс означает, что каждые 20 миллисекунд будет запускаться новая анимация. Для 40 спрайтов общее время "разворачивания" всего эффекта составит 780 мс (39 интервалов * 20 мс). Это создаёт плавный, динамичный визуальный поток. Если увеличить задержку, эффект станет более размеренным, если уменьшить — более резким и одновременным.

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

Метод staggerPlay — это отличный пример того, как Phaser предоставляет высокоуровневые инструменты для создания сложных визуальных явлений с минимальными усилиями. Попробуйте поэкспериментировать: измените задержку на отрицательное число, чтобы анимация запускалась с конца массива, или примените staggerPlay к объектам, расположенным по кругу с помощью Phaser.Actions.PlaceOnCircle. Это открывает двери для создания анимационных последовательностей для заклинаний, волн урона, активации механизмов и многого другого.