О чем этот пример
Загрузка каждого изображения, аудиофайла или 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-пачку автоматически на этапе сборки проекта с помощью скриптов.
