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

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

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        //  This pack will load pack3.json as well
        this.load.pack('pack1', 'assets/loader-tests/pack2.json');
    }

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

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

const game = new Phaser.Game(config);

Что такое файловая пачка (File Pack)?

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

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

Анализ примера: от пачки к изображениям на сцене

Разберем предоставленный пример по шагам. В методе preload() всего одна строка загрузки, но она тянет за собой целую цепочку ресурсов.

this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.pack('pack1', 'assets/loader-tests/pack2.json');

Первая строка устанавливает базовый URL, от которого будут разрешаться все относительные пути в пачке. Вторая — ключевая. Она инициирует загрузку пачки с ключом 'pack1' из указанного JSON-файла. Ключ 'pack1' в данном примере используется как внутренний идентификатор операции загрузки.

Код в create() уверенно использует текстуры, как будто они были загружены прямо здесь. Это и есть магия pack(): он сам вызвал нужные методы загрузки (image, atlas и т.д.) на основе описания в JSON.

Как устроен JSON файл пачки (pack2.json)?

Хотя в примере не показано содержимое pack2.json, стандартная структура пачки выглядит так. Это массив объектов, каждый из которых описывает один ресурс или вложенную пачку.

[
    {
        "type": "image",
        "key": "taikodrummaster",
        "url": "assets/loader-tests/taikodrummaster.png"
    },
    {
        "type": "image",
        "key": "sukasuka-chtholly",
        "url": "assets/loader-tests/sukasuka-chtholly.png"
    },
    {
        "type": "pack",
        "key": "anotherPack",
        "url": "assets/loader-tests/pack3.json"
    }
]

В примере используется вложенность: комментарий в коде говорит, что pack2.json загружает и pack3.json. Именно так и работает объект с "type": "pack". Phaser рекурсивно обрабатывает такие ссылки, загружая все зависимые ресурсы. Поля key для изображений становятся ключами текстуры в кэше, которые затем используются в this.add.image().

Практические шаги для использования в своем проекте

1. **Создайте JSON-файл.** Опишите в нем все ресурсы для сцены или этапа загрузки. 2. **Укажите корректные пути.** Используйте setBaseURL() или абсолютные/относительные пути в url. 3. **Загрузите пачку в preload().** Вызовите this.load.pack() с уникальным ключом и путем к вашему JSON. 4. **Используйте ресурсы по их ключам.** После завершения загрузки в create() и других методах обращайтесь к ассетам по значениям key, указанным в пачке.

Важный момент: порядок загрузки внутри пачки не гарантирован. Если ресурс B зависит от A (например, атлас и его JSON), используйте отдельные вызовы pack() или опцию data для явного указания порядка.

// Альтернативный способ: загрузка пачки из объекта, а не из файла
const myAssets = [
    { "type": "image", "key": "logo", "url": "img/logo.png" }
];
this.load.pack({ key: 'startup', data: myAssets });

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

Использование this.load.pack() — это переход от микроуправления каждым файлом к декларативному описанию ресурсов. Этот метод незаменим для средних и крупных проектов, где количество ассетов измеряется десятками и сотнями. Для экспериментов попробуйте: создать пачку для целого игрового уровня, включая карты (tilemaps), спрайтшиты и звуки; реализовать прогрессивную загрузку уровней через отдельные пачки; или сгенерировать JSON-пачку автоматически на этапе сборки проекта с помощью скриптов.