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

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

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.spritesheet('explosion', 'assets/sprites/explosion.png', { frameWidth: 64, frameHeight: 64, endFrame: 23 });
        this.load.spritesheet('balls', 'assets/sprites/balls.png', { frameWidth: 17, frameHeight: 17 });
    }

    create ()
    {
        const config = {
            key: 'explodeAnimation',
            frames: this.anims.generateFrameNumbers('explosion', { start: 0, end: 23, first: 23 }),
            frameRate: 20,
            repeat: -1
        };

        this.anims.create(config);

        this.add.sprite(400, 300, 'explosion').play('explodeAnimation');

        this.add.sprite(400, 300, 'balls', 3);
    }
}

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

const game = new Phaser.Game(config);

Загрузка спрайт-листов в методе `preload`

Первый шаг — загрузка графических ресурсов. Phaser предлагает метод this.load.spritesheet(), который специально предназначен для работы с изображениями, содержащими последовательность кадров.

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

this.load.spritesheet('explosion', 'assets/sprites/explosion.png', { frameWidth: 64, frameHeight: 64, endFrame: 23 });
this.load.spritesheet('balls', 'assets/sprites/balls.png', { frameWidth: 17, frameHeight: 17 });

В первом вызове также указан параметр endFrame: 23. Это подсказка для загрузчика, что в спрайт-листе нам нужно только 24 кадра (с 0 по 23). Во втором вызове параметр не указан, и Phaser нарежет все изображение на кадры размером 17x17 пикселей.

Важно задавать точные размеры кадра, соответствующие реальному расположению кадров в файле-исходнике.

Создание анимации из загруженных кадров

После загрузки ресурсов можно создать анимацию. Это делается в методе create с помощью this.anims.create(). Метод ожидает объект конфигурации, который описывает анимацию.

Ключевой параметр frames формируется с помощью вспомогательного метода this.anims.generateFrameNumbers(). Этот метод автоматически создает массив кадров для анимации, используя ключ загруженного спрайт-листа и диапазон кадров.

const config = {
    key: 'explodeAnimation',
    frames: this.anims.generateFrameNumbers('explosion', { start: 0, end: 23, first: 23 }),
    frameRate: 20,
    repeat: -1
};

this.anims.create(config);

Разберем параметры конфигурации: * key: Уникальное имя анимации для её последующего запуска. * frames: Массив кадров. generateFrameNumbers('explosion', { start: 0, end: 23, first: 23 }) создает массив из 24 кадров (0-23) спрайт-листа 'explosion'. Параметр first: 23 указывает, какой кадр будет показан до начала воспроизведения анимации. * frameRate: Скорость проигрывания в кадрах в секунду. * repeat: Количество повторений. Значение -1 означает бесконечный цикл.

Отображение и управление анимацией на сцене

Созданную анимацию можно применить к любому спрайту на сцене. В примере используется два подхода.

Первый — создать спрайт и сразу проиграть на нём анимацию с помощью метода .play().

this.add.sprite(400, 300, 'explosion').play('explodeAnimation');

Здесь: 1. this.add.sprite(400, 300, 'explosion') — создает спрайт в координатах (400, 300), используя в качестве текстуры первый кадр спрайт-листа 'explosion'. 2. .play('explodeAnimation') — запускает на этом спрайте анимацию с ключом 'explodeAnimation'. Спрайт автоматически переключит свою текстуру на кадры, указанные в анимации.

Второй подход — отображение одного конкретного кадра из спрайт-листа без анимации. Для этого в метод sprite после ключа текстуры передается индекс кадра (нумерация с нуля).

this.add.sprite(400, 300, 'balls', 3);

Этот код создаст спрайт, который отобразит четвертый кадр (индекс 3) из спрайт-листа 'balls'. Этот метод полезен для статичных объектов, хранящихся в общем атласе.

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

Работа со спрайт-листами и анимациями в Phaser 3 — это основа для создания динамичной графики в играх. Вы научились загружать листы, конфигурировать из них анимированные последовательности и управлять их воспроизведением на сцене. Для экспериментов попробуйте изменить параметр repeat на положительное число, чтобы анимация проигралась несколько раз и остановилась. Или создайте несколько анимаций с разными frameRate из одного спрайт-листа, чтобы получить эффекты медленного тления и быстрого взрыва. Используйте метод .stop() на спрайте, чтобы прервать воспроизведение анимации по какому-либо игровому событию.