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

В игровой разработке производительность напрямую зависит от эффективной загрузки и отрисовки графики. Использование текстурных атласов — стандартный приём для сокращения количества сетевых запросов и draw calls. Phaser предоставляет метод `load.multiatlas()`, который позволяет загружать атласы, разбитые на несколько файлов изображений. Это особенно полезно для больших игр, где единый атлас может быть слишком громоздким. В этой статье мы разберём пример загрузки мульти-атласа, сгенерированного Texture Packer, и его практическое использование для создания случайных спрайтов на сцене.

Версия 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.setPath('assets/loader-tests/');
        // this.load.multiatlas('megaset', 'texture-packer-multi-atlas.json');

        this.load.multiatlas('megaset', 'assets/loader-tests/texture-packer-multi-atlas.json', 'assets/loader-tests/');
    }

    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);

Что такое мульти-атлас и зачем он нужен

Текстурный атлас — это большое изображение, содержащее множество мелких спрайтов, и JSON-файл с координатами каждого из них. Это позволяет загрузить одну текстуру вместо сотен отдельных файлов, что сильно ускоряет загрузку игры и уменьшает нагрузку на GPU.

Однако, когда проект растёт, атлас может превысить максимально допустимые размеры текстуры для целевых устройств (например, 2048x2048). На помощь приходят мульти-атласы, где спрайты распределены по нескольким файлам PNG, но описаны в едином JSON. Phaser корректно обрабатывает такую структуру, предоставляя разработчику единый ключ для работы со всеми кадрами, как если бы это был один атлас.

В этом примере используется JSON, сгенерированный утилитой Texture Packer с опцией 'Multi-atlas'.

Настройка базового URL и загрузка мульти-атласа

Первым шагом в методе preload() мы задаём базовый URL для всех загружаемых ресурсов. Это удобно, если все ассеты хранятся на одном удалённом сервере или в определённой директории проекта.

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

Затем вызывается ключевой метод load.multiatlas(). Он принимает три аргумента: уникальный ключ атласа для последующего обращения, путь к JSON-файлу с описанием, и опциональный базовый путь к самим изображениям (textureURL). Если изображения лежат в той же папке, что и JSON, третий аргумент можно опустить.

this.load.multiatlas('megaset', 'assets/loader-tests/texture-packer-multi-atlas.json', 'assets/loader-tests/');

Phaser загрузит JSON, проанализирует его, и автоматически загрузит все связанные файлы изображений, указанные внутри (например, texture-packer-multi-atlas-0.png, texture-packer-multi-atlas-1.png).

Получение текстуры и списка кадров

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

const atlasTexture = this.textures.get('megaset');

Объект Texture содержит всю информацию об атласе. Метод getFrameNames() возвращает массив строк — имён всех индивидуальных кадров (спрайтов), которые содержатся в мульти-атласе. Это имена, которые были заданы в исходных файлах или в Texture Packer.

const frames = atlasTexture.getFrameNames();

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

Создание случайных спрайтов на сцене

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

const x = Phaser.Math.Between(0, 1024);
const y = Phaser.Math.Between(0, 768);

Затем создаётся изображение (Image — игровой объект Phaser). В конструктор передаётся: 1. Ключ текстуры атласа ('megaset'). 2. Имя конкретного кадра для отображения (frames[i]).

this.add.image(x, y, 'megaset', frames[i]);

Важно понимать, что несмотря на то, что физически изображения лежат в нескольких PNG-файлах, в коде мы работаем с единым атласом 'megaset'. Phaser сам определяет, из какого файла брать нужный кадр, основываясь на данных из JSON.

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

Использование load.multiatlas() — это мощный и необходимый инструмент для управления графическими ресурсами в больших проектах Phaser. Он сохраняет все преимущества текстурных атласов, решая проблему ограничений по размеру текстуры. Для экспериментов вы можете: попробовать сгенерировать свой мульти-атлас в Texture Packer или подобной утилите; изменить код, чтобы спрайты появлялись не случайно, а в определённом порядке для создания анимации; или загрузить несколько разных мульти-атласов и переключаться между ними в зависимости от игровой сцены.