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

Загрузка каждого изображения, звука или JSON-файла по отдельности быстро превращается в рутину. Phaser 3 предлагает мощный инструмент – загрузку через `pack` (пакеты). Это позволяет декларативно описать целую группу ресурсов в структурированном объекте или JSON-файле, что делает код загрузки чистым, централизованным и легко редактируемым. В статье разберем, как создавать и использовать такие пакеты прямо из кода, без внешних файлов.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    FilePackObject = {
        test1: {
            files: [
                {
                    type: 'image',
                    key: 'taikodrummaster',
                    url: 'assets/pics/taikodrummaster.jpg'
                },
                {
                    type: 'image',
                    key: 'sukasuka-chtholly',
                    url: 'assets/pics/sukasuka-chtholly.png'
                }
            ]
        },
        test2: {
            prefix: 'TEST2.',
            path: 'assets/pics',
            defaultType: 'image',
            files: [
                {
                    key: 'donuts',
                    extension: 'jpg'
                },
                {
                    key: 'ayu'
                }
            ]
        },
        meta: {
            generated: '1401380327373',
            app: 'Phaser 3 Asset Packer',
            url: 'https://phaser.io',
            version: '1.0',
            copyright: 'Photon Storm Ltd. 2018'
        }
    };

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.pack('pack1', this.FilePackObject);
    }

    create ()
    {
        this.add.image(400, 300, 'taikodrummaster');
        this.add.image(400, 500, 'sukasuka-chtholly');
    }
}

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

const game = new Phaser.Game(config);

Что такое File Pack и зачем он нужен

Метод this.load.pack() – это системный загрузчик Phaser, предназначенный для приема структурированного описания множества ресурсов. Вместо последовательных вызовов this.load.image() и this.load.audio() вы определяете один объект, который содержит метаданные и список файлов.

Основные преимущества: * **Читаемость и поддержка:** Все ресурсы для сцены или игры описаны в одном месте. * **Гибкость:** Можно задавать общие настройки для группы файлов (префикс ключа, базовый путь). * **Удобство:** Легко добавлять, удалять или комментировать загружаемые ассеты.

В нашем примере весь пакет описан прямо в классе сцены как свойство FilePackObject, но его также можно загрузить из внешнего JSON-файла.

Структура объекта пакета

Объект пакета – это обычный JavaScript-объект. Каждый его корневой ключ (например, test1, test2) определяет отдельную группу загрузки. Внутри группы можно задавать общие свойства и массив файлов.

Рассмотрим первую группу, test1:

test1: {
    files: [
        {
            type: 'image',
            key: 'taikodrummaster',
            url: 'assets/pics/taikodrummaster.jpg'
        },
        // ...
    ]
}

Здесь для каждого файла в массиве files явно указаны его type, уникальный key для последующего использования и полный url. Это самый прямой способ описания.

Вторая группа, test2, демонстрирует использование общих настроек для упрощения:

test2: {
    prefix: 'TEST2.',
    path: 'assets/pics',
    defaultType: 'image',
    files: [
        { key: 'donuts', extension: 'jpg' },
        { key: 'ayu' }
    ]
}

* prefix: Добавится к key каждого файла. Итоговый ключ для первого изображения будет 'TEST2.donuts'. * path: Базовый путь, который будет подставлен к key для формирования URL. * defaultType: Тип ресурса по умолчанию для всех файлов в группе. * В массиве files теперь нужно указать только key и, опционально, extension (если оно отличается от стандартного для типа). Phaser сам соберет итоговый URL по схеме: path + '/' + key + '.' + extension.

Загрузка пакета в сцене

Инициализация загрузки происходит в методе `preload()`. Ключевые шаги:
1.  Установка базового URL для всех последующих загрузок через `this.load.setBaseURL()`. Это удобно, если все ресурсы лежат на одном домене или в одном репозитории.
2.  Непосредственный вызов `this.load.pack()` для запуска загрузки пакета.
preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.pack('pack1', this.FilePackObject);
}

Метод pack() принимает два аргумента: * key (строка): Произвольный ключ для данного пакета. Может быть полезен, если пакетов несколько. * data (объект или строка): Данные пакета. Это может быть объект (как в нашем случае) или URL к внешнему JSON-файлу.

После выполнения этого кода Phaser проанализирует объект FilePackObject и поставит в очередь на загрузку все указанные в нем файлы.

Использование загруженных ассетов

После того как пакет загружен в preload(), использовать ресурсы в create() и других методах сцены можно стандартным образом – по их ключу (key). Важно помнить, как формировался итоговый ключ.

create ()
{
    // Ключи из группы test1 (указаны явно)
    this.add.image(400, 300, 'taikodrummaster');
    this.add.image(400, 500, 'sukasuka-chtholly');

    // Ключи из группы test2 (сформированы с prefix)
    // this.add.image(200, 300, 'TEST2.donuts');
    // this.add.image(600, 300, 'TEST2.ayu');
}

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

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

Использование this.load.pack() – отличный способ привести код загрузки ресурсов в порядок. Это особенно актуально для проектов с десятками и сотнями ассетов. Для экспериментов попробуйте

  1. Вынести объект пакета в отдельный JSON-файл и загружать его по URL
  2. Добавить в пакет ресурсы разных типов (аудио, атласы, bitmap-шрифты)
  3. Создать несколько пакетов для разных уровней игры и загружать их динамически