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

Анимация спрайтов — один из краеугольных камней игровой разработки. Пример с лошадью Мейбриджа демонстрирует не просто воспроизведение последовательности кадров, а мощный механизм синхронизации анимации на нескольких спрайтах с помощью `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.spritesheet('muybridge', 'assets/animations/muybridge01.png', { frameWidth: 119, frameHeight: 228 });
    }

    create ()
    {
        const config = {
            key: 'run',
            frames: 'muybridge',
            frameRate: 15,
            repeat: -1
        };

        this.anims.create(config);

        //  Each frame is 119px wide

        const group = this.add.group();

        group.createMultiple({
            key: 'muybridge',
            frame: 10,
            repeat: 7,
            setOrigin: { x: 0, y: 0.5 },
            setXY: { x: 0, y: 300, stepX: 119 }
        });

        this.anims.staggerPlay('run', group.getChildren(), -100, false);
    }
}

const config = {
    type: Phaser.WEBGL,
    parent: 'phaser-example',
    width: 952,
    height: 600,
    backgroundColor: '#efefef',
    scene: Example
};

const game = new Phaser.Game(config);

Загрузка спрайтшита

Перед созданием анимации необходимо загрузить ресурс. В методе preload используется this.load.spritesheet. Важно корректно указать размер одного кадра, чтобы Phaser мог автоматически разрезать изображение.

this.load.spritesheet('muybridge', 'assets/animations/muybridge01.png', { frameWidth: 119, frameHeight: 228 });

Здесь 'muybridge' — это ключ, по которому мы будем обращаться к спрайтшиту. Параметры frameWidth и frameHeight определяют размер каждого кадра анимации в пикселях. Без этих данных Phaser не сможет корректно разделить изображение на отдельные кадры (фреймы).

Создание конфигурации анимации

Анимация в Phaser создаётся через менеджер this.anims. Для этого необходимо определить её конфигурацию.

const config = {
    key: 'run',
    frames: 'muybridge',
    frameRate: 15,
    repeat: -1
};

this.anims.create(config);

- key: Уникальный ключ анимации. По нему мы будем её запускать. - frames: Ключ загруженного спрайтшита. Phaser автоматически создаст массив кадров из всех фреймов изображения. - frameRate: Скорость воспроизведения в кадрах в секунду. - repeat: Количество повторений. Значение -1 означает бесконечный цикл анимации.

Создание группы спрайтов

Для эффекта последовательного движения нам нужно несколько экземпляров одного и того же спрайта. Идеально для этого подходит Group.

const group = this.add.group();

group.createMultiple({
    key: 'muybridge',
    frame: 10,
    repeat: 7,
    setOrigin: { x: 0, y: 0.5 },
    setXY: { x: 0, y: 300, stepX: 119 }
});

- key и frame: Создаёт спрайты, используя ключ ресурса и конкретный кад (в данном случае, 10-й) в качестве стартового изображения. - repeat: Создаёт 7 дополнительных спрайтов, всего их станет 8 (1 исходный + 7 повторений). - setOrigin: Устанавливает точку вращения и выравнивания. { x: 0, y: 0.5 } означает, что спрайт будет выровнен по левому краю и центру по вертикали. - setXY: Располагает первый спрайт в координатах (0, 300). Параметр stepX: 119 автоматически сдвигает каждый следующий спрайт на 119 пикселей по оси X, что равно ширине одного кадра. Это критически важно для бесшовного эффекта.

Синхронизированный запуск анимации

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

this.anims.staggerPlay('run', group.getChildren(), -100, false);

- Первый аргумент 'run' — ключ созданной ранее анимации. - Второй аргумент group.getChildren() — массив всех спрайтов в группе. - Третий аргумент -100 — время задержки (stagger) в миллисекундах между запуском анимации на соседних спрайтах. Отрицательное значение означает, что анимация будет запускаться от последнего спрайта к первому, создавая волну. - Четвёртый аргумент false указывает, что метод должен использовать переданный массив спрайтов как есть, без перемешивания или сложной логики выбора.

В результате анимация на каждом следующем спрайте начинается на 100 мс позже, чем на предыдущем, создавая иллюзию плавного движения лошади по экрану.

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

Метод staggerPlay — это мощный инструмент для управления временем в анимациях Phaser. Он позволяет легко создавать сложные последовательности без ручного управления таймерами для каждого объекта. Для экспериментов попробуйте изменить знак задержки на положительный, чтобы изменить направление "волны". Или используйте этот приём для анимации фоновых элементов (облака, волны) или для визуализации цепочки событий, например, последовательного загорания огней на панели управления.