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

В разработке игр важно не только создать красивые ассеты, но и эффективно их загружать. Мультиатласы (Multi-Atlas) — это продвинутый формат упаковки текстур, который позволяет разделить большой набор спрайтов на несколько файлов изображений, сохранив при этом единый файл данных с координатами. Этот подход особенно полезен для уменьшения времени загрузки и управления памятью при работе с большими коллекциями графики, например, в сложных анимациях или интерфейсах. В этой статье мы разберем, как загружать и использовать мультиатласы в Phaser на примере с форматом WebP, что даст вам практический инструмент для оптимизации ваших игровых проектов.

Версия 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.multiatlas('game', 'assets/atlas/multi-webp.json', 'assets/atlas/');
    }

    create ()
    {
        const atlasTexture = this.textures.get('game');

        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, 'game', frames[i]);
        }
    }
}

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

const game = new Phaser.Game(config);

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

Традиционный текстурный атлас — это один большой файл изображения (PNG, JPEG, WebP) и один JSON-файл с координатами (data file). Мультиатлас расширяет эту концепцию: один JSON-файл данных может ссылаться на несколько файлов изображений. Это решает несколько проблем:

- **Оптимизация загрузки**: Браузер может параллельно загружать несколько небольших файлов вместо одного огромного, что часто быстрее. - **Управление памятью**: Вы можете выгружать неиспользуемые части атласа (например, текстур для уровня 2, пока игрок на уровне 1). - **Гибкость**: Разные типы ассетов (персонаж, окружение, UI) можно хранить в отдельных файлах, но использовать как единый атлас через общий ключ.

В примере используется формат WebP — современный формат сжатия, обеспечивающий высокое качество при малом размере файла.

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

Загрузка ресурсов в Phaser происходит в методе preload сцены. Первым делом мы задаем базовый URL для всех последующих загрузок через this.load.setBaseURL. Это удобно, если все ваши ассеты лежат в одной корневой папке на сервере.

Затем мы загружаем сам мультиатлас с помощью метода this.load.multiatlas. Важно передать ему три аргумента.

this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.multiatlas('game', 'assets/atlas/multi-webp.json', 'assets/atlas/');

- 'game' — это уникальный ключ (текстурный ключ), по которому мы будем обращаться к загруженному атласу в игре. - 'assets/atlas/multi-webp.json' — путь к JSON-файлу данных атласа относительно базового URL. - 'assets/atlas/' — путь к папке, где лежат файлы изображений (.webp), на которые ссылается JSON. Phaser автоматически подставит этот путь к именам файлов из JSON.

Структура JSON-файла для мультиатласа

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

Пример структуры (сокращенно):

{
  "textures": [
    {
      "image": "game-0.webp", // Имя файла изображения
      "format": "RGBA8888",
      "size": {"w": 512, "h": 512},
      "scale": 1,
      "frames": [
        // ... массив фреймов с координатами для этого файла
      ]
    },
    {
      "image": "game-1.webp",
      // ... данные для второго файла
    }
  ]
}

Метод multiatlas парсит этот файл, загружает все указанные изображения (game-0.webp, game-1.webp и т.д.) и создает в системе текстур (this.textures) единую текстуру с ключом 'game', объединяя все фреймы из всех файлов.

Доступ к текстуре и создание изображений

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

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

Объект atlasTexture содержит всю информацию об атласе. Метод getFrameNames() возвращает массив строк с именами всех доступных фреймов (например, ['background', 'player_idle_01', 'enemy_walk_02']).

Затем пример в цикле создает несколько изображений на сцене, используя случайные координаты.

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, 'game', frames[i]);
}

- Phaser.Math.Between генерирует случайное целое число в заданном диапазоне для позиций X и Y. - this.add.image создает игровой объект Image. Четвертый аргумент frames[i] указывает, какой именно кадр из атласа 'game' использовать для этого изображения. Phaser автоматически найдет координаты этого фрейма в одном из загруженных файлов изображений.

Конфигурация игры и запуск сцены

Весь код должен быть запущен в контексте игры Phaser. Конфигурационный объект config определяет основные параметры.

const config = {
    type: Phaser.AUTO,
    width: 1024,
    height: 768,
    parent: 'phaser-example',
    scene: Example
};
const game = new Phaser.Game(config);

- type: Phaser.AUTO позволяет Phaser самому выбрать рендерер (WebGL или Canvas). - width / height: Размер игрового холста. - parent: ID HTML-элемента, в который будет встроен canvas игры. Если элемента с таким ID нет, canvas будет добавлен в тело документа. - scene: Класс сцены, которая будет запущена сразу после инициализации игры. В нашем случае это Example, где определены методы preload и create. Создание экземпляра new Phaser.Game(config) запускает весь процесс.

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

Использование мультиатласов в Phaser — это мощный прием для оптимизации загрузки графики в ваших играх. Вы научились загружать такой атлас с помощью load.multiatlas, получать доступ ко всем его фреймам и создавать из них игровые объекты. Для экспериментов попробуйте: создать свой мультиатлас с помощью инструментов вроде TexturePacker или Shoebox; динамически добавлять и удалять отдельные текстуры из мультиатласа в runtime; использовать мультиатласы для анимаций спрайтов, подключая this.anims.create. Это откроет новые возможности для структурирования ресурсов в больших проектах.