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

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

Версия 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.setPath('assets/sprites');

        //  An array of sprite sheets.
        //  The URLs are automatically created based on the path and key (see documentation for details)
        this.load.spritesheet([
            { key: 'explosion', frameConfig: { frameWidth: 64, frameHeight: 64, endFrame: 23 } },
            { key: 'balls', frameConfig: { 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);

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

Перед загрузкой спрайт-листов полезно задать базовый URL и путь. Это избавляет от необходимости указывать полный путь для каждого ресурса, делая код более адаптивным и чистым.

Метод this.load.setBaseURL() устанавливает корневой адрес, от которого будут строиться все последующие пути. Метод this.load.setPath() добавляет к нему конкретную папку с ассетами. В нашем примере все спрайты будут искаться в указанной папке на GitHub.

this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.setPath('assets/sprites');

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

Ключевой метод — this.load.spritesheet(). Обычно он принимает ключ, путь и конфигурацию кадра. Однако его мощная перегрузка позволяет передать массив объектов. Каждый объект в массиве должен содержать обязательное поле key и объект frameConfig.

Phaser автоматически сформирует конечный URL для загрузки, используя ключ как имя файла и добавленный ранее базовый путь. Это означает, что для ключа 'explosion' движок попробует загрузить файл по адресу: базовый URL + путь + ключ + расширение файла по умолчанию (например, .png).

this.load.spritesheet([
    { key: 'explosion', frameConfig: { frameWidth: 64, frameHeight: 64, endFrame: 23 } },
    { key: 'balls', frameConfig: { frameWidth: 17, frameHeight: 17 } }
]);

В frameConfig указывается ширина и высота одного кадра (frameWidth, frameHeight), а также опциональные параметры вроде endFrame — индекса последнего кадра для загрузки.

Создание и использование анимации

После загрузки ресурсы доступны в кеше по своим ключам. Спрайт-лист 'explosion' идеально подходит для создания анимации. Для этого используется система анимаций Phaser.

Сначала с помощью this.anims.generateFrameNumbers() генерируется массив описаний кадров. Мы указываем ключ спрайт-листа и диапазон кадров. Параметр first задаёт кадр, который будет показан до начала воспроизведения анимации.

Затем this.anims.create() регистрирует новую анимацию в менеджере, используя сгенерированные кадры и заданную частоту (frameRate). Значение repeat: -1 делает анимацию зацикленной.

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

Созданный спрайт с ключом 'explosion' сразу может проигрывать эту анимацию методом .play().

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

Использование статичного кадра из спрайт-листа

Не все спрайт-листы предназначены для анимации. Некоторые, как 'balls' в примере, содержат набор разных статичных изображений (например, шарики разного цвета).

Чтобы отобразить конкретный кадр такого листа, нужно передать его индекс четвертым параметром в this.add.sprite(). Индексация начинается с нуля.

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

Этот код создаст спрайт в координатах (400, 300), используя текстуру 'balls' и отобразив кадр с индексом 3.

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

Использование массовой загрузки спрайт-листов через массив объектов — это профессиональный приём, который значительно структурирует код загрузки в preload(). Он минимизирует повторения, снижает вероятность ошибок и облегчает масштабирование проекта. Для экспериментов попробуйте: добавить в массив загрузки третий спрайт-лист; использовать разные конфигурации кадров (startFrame, margin, spacing); или динамически формировать массив для загрузки на основе данных из конфигурационного JSON-файла.