О чем этот пример
Phaser предоставляет мощные инструменты для организации загрузки ресурсов. Однако при работе с JSON-паками не всегда очевидно, как загрузить не весь пакет целиком, а лишь его часть. Эта статья на практическом примере показывает, как использовать третий, необязательный параметр `dataKey` в методе `this.load.pack()`, чтобы точечно управлять загрузкой ассетов. Вы научитесь структурировать большие наборы ресурсов и загружать только то, что нужно для конкретной сцены или игрового режима.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
const data = {
test1: {
files: [
{
type: 'image',
key: 'beer',
url: 'assets/sprites/beer.png'
},
{
type: 'image',
key: 'donut',
url: 'assets/sprites/donut.png'
},
]
},
test2: {
files: [
{
type: 'image',
key: 'ginger',
url: 'assets/sprites/gingerbread.png'
},
{
type: 'image',
key: 'hotdog',
url: 'assets/sprites/hotdog.png'
},
]
}
}
class Example extends Phaser.Scene
{
constructor ()
{
super();
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
// this.load.pack('pack', data);
this.load.pack('pack', data, 'test1');
// this.load.json('bob', data, 'test2');
}
create ()
{
// console.log(this.cache.json.get('bob'));
this.add.image(400, 300, 'beer');
// this.add.image(400, 300, 'hotdog');
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#2d2d6d',
scene: Example
};
const game = new Phaser.Game(config);
Проблема: один JSON, много ресурсов
Представьте, что вы создаёте масштабную игру, где ассеты логически разделены по уровням, локациям или персонажам. Хранить ссылки на все файлы в одном месте удобно для управления, но загружать всё сразу — неэффективно. Это увеличивает время начальной загрузки и расходует память.
Исходный код демонстрирует как раз такую структуру данных. В объекте data есть два вложенных объекта (test1 и test2), каждый из которых содержит свой массив файлов (files).
Решение: параметр dataKey в load.pack
Метод this.load.pack() имеет следующую сигнатуру:
this.load.pack(key, url, dataKey, xhrSettings)
Третий параметр, dataKey, — это строка, указывающая на конкретный ключ внутри вашего JSON-объекта. Phaser загрузит только ту часть данных, которая находится по этому ключу.
В примере, чтобы загрузить только изображения из раздела test1 (пиво и пончик), используется вызов:
this.load.pack('pack', data, 'test1');
Без указания dataKey Phaser попытается интерпретировать весь объект data как конфигурацию пакета, что может привести к ошибке, если структура не соответствует ожидаемой для корневого уровня пакета.
Сравнение с load.json
Важно не путать load.pack с load.json. Метод load.json загружает или обрабатывает JSON-файл как данные, доступные через кэш (this.cache.json). Он не запускает автоматическую загрузку файлов, описанных внутри этого JSON.
Закомментированная строка в примере показывает этот подход:
// this.load.json('bob', data, 'test2');
После такой загрузки объект data['test2'] стал бы доступен через this.cache.json.get('bob'). Однако изображения ginger и hotdog не были бы загружены в текстуры, и попытка создать спрайт с ключом hotdog вызвала бы ошибку. Метод pack делает больше — он не только сохраняет данные, но и ставит файлы из files в очередь на загрузку.
Практическое применение в сцене
В методе create() сцены создаётся спрайт, используя ключ beer, который был определён и загружен благодаря вызову load.pack('pack', data, 'test1').
this.add.image(400, 300, 'beer');
Если бы мы загружали раздел test2 и попытались создать спрайт hotdog, он бы отобразился корректно. Попытка же использовать незагруженный ключ (например, раскомментировав строку с hotdog, не загрузив test2) привела бы к ошибке в консоли и пустому месту на экране.
Этот механизм идеально подходит для загрузки ресурсов для конкретного уровня игры прямо перед его стартом в методе preload() сцены этого уровня.
Что попробовать дальше
Использование параметра dataKey в this.load.pack() — это мощный паттерн для модульной загрузки ресурсов. Он позволяет держать все описания ассетов в одном JSON-файле, но загружать их порционно, по мере необходимости. Для экспериментов попробуйте:
1. Создать структуру данных с разделами для разных типов врагов или боссов и загружать их пакетно перед битвой.
2. Динамически определять, какой dataKey загружать, на основе выбора игрока или прогресса.
3. Комбинировать несколько вызовов load.pack с разными ключами в одной сцене для сборки необходимого набора ассетов.
