О чем этот пример
Загрузка игровых ассетов по одному — утомительный и чреватый ошибками процесс. Особенно когда речь идет о десятках изображений, атласов и звуков. Метод `load.pack()` в Phaser позволяет описать все необходимые ресурсы в одном JSON-файле и загрузить их одной командой. Это делает код чище, упрощает управление ассетами и ускоряет процесс разработки. В этой статье мы разберем, как работает загрузка пачками на конкретном примере, и покажем, как это применить в ваших проектах.
Версия 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.pack('pack', 'assets/loader-tests/pack4.json');
}
create ()
{
const atlasTexture = this.textures.get('megaset');
const frames = atlasTexture.getFrameNames();
for (let i = 0; i < frames.length; i++)
{
const x = Phaser.Math.Between(0, 1024);
const y = Phaser.Math.Between(0, 768);
this.add.image(x, y, 'megaset', frames[i]);
}
}
}
const config = {
type: Phaser.AUTO,
width: 1024,
height: 768,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое pack-файл и зачем он нужен
Pack-файл в Phaser — это JSON-объект, который описывает список ресурсов для загрузки. Вместо того чтобы вызывать this.load.image() или this.load.atlas() для каждого отдельного ассета в методе preload(), вы создаете структурированный список в отдельном файле. Это разделяет логику загрузки (что грузить) и её конфигурацию (откуда и как грузить).
Такой подход особенно полезен для: * **Атласов спрайтов:** когда у вас один файл изображения и один файл данных (JSON или XML). * **Звуков:** загрузка нескольких форматов (mp3, ogg) для одного звукового эффекта. * **Больших проектов:** удобно разделять ассеты по уровням или сценам в разные pack-файлы.
В исходном примере pack-файл расположен по адресу assets/loader-tests/pack4.json относительно установленного базового URL.
Настройка базового URL и загрузка пачки
Первым делом в методе preload() сцены нужно настроить базовый путь для всех последующих загрузок. Это делается с помощью метода load.setBaseURL(). После этого можно загрузить сам pack-файл.
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.pack('pack', 'assets/loader-tests/pack4.json');
Метод load.pack() принимает два ключевых аргумента:
1. **Ключ (key):** 'pack' — произвольная строка-идентификатор для этой конкретной пачки. Он может пригодиться, если вы используете несколько pack-файлов и события для отслеживания их загрузки.
2. **URL:** 'assets/loader-tests/pack4.json' — путь к JSON-файлу с описанием ресурсов. Этот путь строится относительно базового URL, установленного ранее.
После вызова этого метода Phaser асинхронно загрузит указанный JSON, распарсит его и начнет загрузку всех описанных внутри ресурсов.
Использование загруженных ресурсов в create()
Как только все ресурсы из пачки загружены, Phaser автоматически переходит к методу create() сцены. В этот момент текстуры, звуки и другие ассеты уже доступны в соответствующих кэшах (this.textures, this.cache и т.д.).
В нашем примере pack-файл содержал описание для текстуры атласа с ключом 'megaset'. Чтобы получить доступ к этой текстуре, используется менеджер текстур:
const atlasTexture = this.textures.get('megaset');
Далее, чтобы отобразить каждый отдельный кадр (спрайт) из этого атласа, нам нужно получить список их имен. Это делает метод getFrameNames():
const frames = atlasTexture.getFrameNames();
Теперь, имея массив имен кадров, можно создать множество изображений на сцене. В примере это делается в цикле: для каждого имени кадра генерируются случайные координаты, и добавляется изображение.
for (let i = 0; i < frames.length; i++)
{
const x = Phaser.Math.Between(0, 1024);
const y = Phaser.Math.Between(0, 768);
this.add.image(x, y, 'megaset', frames[i]);
}
Ключевые моменты вызова this.add.image():
* **Первый аргумент ('megaset'):** это ключ самой текстуры атласа, который мы использовали в textures.get().
* **Второй аргумент (frames[i]):** это имя конкретного кадра внутри этого атласа, которое мы хотим отобразить.
Структура pack-файла (предположительная)
Хотя в примере не показано содержимое pack4.json, мы можем предположить его структуру, основанную на официальной документации Phaser и итоговому результату (загрузка атласа megaset).
Типичный pack-файл для загрузки атласа в формате JSON Hash (стандартный для Texture Packer) мог бы выглядеть так:
{
"megaset": {
"type": "atlasJSONHash",
"textureURL": "assets/megaset-0.png",
"atlasURL": "assets/megaset-0.json"
}
}
Или, если бы мы загружали несколько ресурсов, структура была бы массивом объектов:
{
"files": [
{
"type": "atlasJSONHash",
"key": "megaset",
"textureURL": "assets/megaset-0.png",
"atlasURL": "assets/megaset-0.json"
},
{
"type": "image",
"key": "background",
"url": "assets/sky.png"
}
]
}
Обратите внимание на поле "key". Именно это значение ('megaset') потом используется для доступа к ресурсу через this.textures.get().
Что попробовать дальше
Использование load.pack() — это мощный шаг к поддержанию порядка в растущем проекте. Он централизует конфигурацию ресурсов, уменьшает объем кода в сценах и упрощает добавление новых ассетов.
**Идеи для экспериментов:**
1. Создайте несколько pack-файлов для разных игровых уровней и загружайте их по мере необходимости, используя ключ пачки для отслеживания завершения загрузки.
2. Попробуйте описать в одном pack-файле не только атласы, но и изображения, аудио, bitmap-шрифты и данные (JSON).
3. Исследуйте событие 'filecomplete-pack' для выполнения кастомной логики сразу после загрузки всей пачки.
