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

Анимации и графические ресурсы — основа визуальной составляющей игры. Однако загрузка множества отдельных изображений может тормозить старт проекта и усложнять управление контентом. Текстурный атлас решает эту проблему, объединяя много спрайтов в один файл изображения с сопутствующим файлом-описанием (JSON). В этой статье мы разберем, как правильно загружать и использовать атласы в Phaser 3, что позволит вам ускорить загрузку игры и упростить работу со спрайтами.

Версия 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.atlas({
            key: 'megaset',
            textureURL: 'assets/atlas/megaset-0.png',
            atlasURL: 'assets/atlas/megaset-0.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, 800);
            const y = Phaser.Math.Between(0, 600);

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

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

const game = new Phaser.Game(config);

Что такое текстурный атлас и зачем он нужен

Текстурный атлас (Texture Atlas) — это один большой файл изображения (PNG), содержащий множество маленьких спрайтов или кадров анимации. Второй файл (обычно в формате JSON) описывает координаты и размеры каждого отдельного элемента (фрейма) внутри этого большого изображения.

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

В примере используется популярный формат атласа, сгенерированный инструментами вроде TexturePacker или Shoebox.

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

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

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

Далее мы используем метод this.load.atlas(). Важная особенность примера — он передает не несколько аргументов, а один объект с настройками. Это современный и наглядный способ загрузки в Phaser.

this.load.atlas({
    key: 'megaset',
    textureURL: 'assets/atlas/megaset-0.png',
    atlasURL: 'assets/atlas/megaset-0.json'
});

* key: 'megaset' — это уникальный идентификатор, по которому мы будем обращаться к загруженному атласу в игре. * textureURL — относительный путь к файлу изображения атласа. * atlasURL — относительный путь к JSON-файлу с данными о фреймах. Phaser автоматически загрузит оба файла и свяжет их в единый ресурс.

Получение данных атласа и создание изображений

Когда ресурсы загружены, управление переходит в метод 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, 800);
    const y = Phaser.Math.Between(0, 600);
    this.add.image(x, y, 'megaset', frames[i]);
}

* Phaser.Math.Between(0, 800) генерирует случайную координату по X в пределах ширины сцены. * this.add.image(x, y, 'megaset', frames[i]) — ключевая строка. Она создает игровой объект Image. Первые два аргумента — координаты, третий — ключ атласа, а четвертый — имя конкретного фрейма из этого атласа. Phaser сам "вырежет" нужную область из большого изображения.

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

Код завершается стандартной для Phaser конфигурацией и созданием экземпляра игры. Это основа любого проекта.

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

const game = new Phaser.Game(config);

* scene: Example — указывает, что наша созданная сцена Example будет использована как начальная сцена игры. * parent: 'phaser-example' — это ID HTML-элемента на странице, внутрь которого Phaser вставит свой canvas.

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

Использование текстурных атласов — это обязательный шаг для оптимизации любой серьезной игры на Phaser. Вы не только ускоряете загрузку, но и делаете код чище. Для экспериментов попробуйте: создать анимацию, последовательно перебирая фреймы из атласа; загрузить несколько атласов для разных уровней игры; или использовать this.add.sprite вместо image, чтобы добавить объекту физическое тело для взаимодействий.