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

В процессе разработки игры количество ресурсов — спрайтов, звуков, данных — быстро растёт. Управлять загрузкой каждого файла по отдельности становится неудобно и громоздко. Phaser предоставляет мощный инструмент — загрузку через JSON-пакеты (File Packs). Этот подход позволяет организовать ассеты в логические группы и загружать их одной строкой кода, что делает код чище, а процесс разработки — быстрее и надёжнее. В этой статье мы разберём, как работает загрузчик Phaser с пакетами, на конкретном примере. Вы научитесь структурировать свои ресурсы и эффективно подгружать только нужные их части в разные сцены игры.

Версия 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('pack1', 'assets/loader-tests/pack1.json', 'test2');
    }

    create ()
    {
        this.add.image(400, 300, 'TEST2.donuts');
        this.add.image(500, 300, 'TEST2.ayu');
    }
}

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

const game = new Phaser.Game(config);

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

File Pack — это JSON-файл, который описывает группу ресурсов (изображения, аудио, атласы и т.д.). Вместо того чтобы вызывать this.load.image(), this.load.audio() для каждого файла в коде сцены, вы описываете все эти вызовы в отдельном конфигурационном файле.

Это даёт несколько преимуществ: * **Организация:** Ассеты можно группировать по сценам, уровням или типам (например, «главное меню», «персонажи», «звуки UI»). * **Переиспользование:** Один пакет можно загрузить в разных сценах. * **Читаемость кода:** Метод preload() сцены становится лаконичным и понятным. * **Гибкость:** Можно загружать не весь пакет целиком, а только выбранную его часть (как в нашем примере).

Разбираем структуру примера: preload()

Давайте посмотрим, как в примере реализована загрузка части пакета.

Сначала в preload() мы настраиваем базовый URL, от которого будут рассчитываться пути ко всем файлам в этом пакете. Это удобно, если все ваши ресурсы лежат в одном корне.

this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');

Затем происходит ключевой вызов — загрузка пакета. Метод load.pack() принимает три аргумента.

this.load.pack('pack1', 'assets/loader-tests/pack1.json', 'test2');

1. **Ключ пакета ('pack1'):** Уникальный идентификатор для этого пакета внутри загрузчика Phaser. 2. **URL пакета ('assets/loader-tests/pack1.json'):** Путь к JSON-файлу с описанием пакета. Путь строится относительно базового URL. 3. **Ключ данных ('test2'):** Самый важный для нашего примера параметр. Он указывает, какую именно *часть* (section) из JSON-пакета нужно загрузить. Если этот параметр опущен, будет загружен весь пакет.

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

После успешной загрузки пакета в методе create() мы можем использовать текстуры. Обратите внимание на имена ключей (keys), по которым к ним обращаются.

this.add.image(400, 300, 'TEST2.donuts');
this.add.image(500, 300, 'TEST2.ayu');

Ключи имеют составной формат: 'TEST2.donuts' и 'TEST2.ayu'. Здесь 'TEST2' — это как раз тот самый ключ данных (dataKey), который мы передали в load.pack(). А 'donuts' и 'ayu' — это имена файлов, определённые внутри соответствующей секции JSON-пакета.

Такой подход позволяет иметь в одном большом пакете несколько независимых групп ассетов и загружать их по мере необходимости, избегая конфликтов имён.

Как может выглядеть JSON-пакет (pack1.json)

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

{
    "test1": [
        { "type": "image", "key": "logo", "url": "assets/logo.png" }
    ],
    "test2": [
        { "type": "image", "key": "donuts", "url": "assets/donuts.png" },
        { "type": "image", "key": "ayu", "url": "assets/ayu.png" }
    ],
    "audioPack": [
        { "type": "audio", "key": "theme", "url": ["audio/main.mp3", "audio/main.ogg"] }
    ]
}

Каждая секция (например, 'test2') — это массив объектов. Каждый объект описывает один файл: его тип (type), ключ для использования в коде (key) и путь к файлу (url). Phaser на основе типа ('image', 'audio', 'atlas' и др.) знает, какой метод загрузки использовать.

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

Использование JSON-пакетов — это профессиональный подход к управлению ресурсами в Phaser. Он отделяет конфигурацию данных от логики игры, что особенно ценно в больших проектах. Вы можете легко добавлять новые ассеты, редактируя JSON-файл, не трогая код сцен. **Идеи для экспериментов:** 1. Создайте пакет с разными типами ассетов (изображения, звуки, атласы спрайтов) и загрузите его целиком, не указывая ключ данных. 2. Напишите скрипт, который будет автоматически генерировать JSON-пакет на основе файлов в вашей папке assets. 3. Реализуйте прогрессивную загрузку: загрузите пакет с ресурсами для главного меню, а после входа в игру — динамически загрузите пакет с ресурсами для первого уровня, используя тот же метод load.pack().