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

Использование текстурных атласов — ключевая техника оптимизации для 2D-игр. Вместо загрузки десятков отдельных файлов изображений вы упаковываете все спрайты в один большой файл и загружаете его вместе с JSON-файлом, описывающим координаты каждого элемента. Это значительно сокращает количество HTTP-запросов, ускоряет загрузку игры и упрощает управление ассетами. В этой статье мы разберем, как загрузить атлас и отображать из него конкретные кадры (frames) на сцене, используя пример из официальной документации 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.atlas('atlas', 'assets/atlas/megaset-1.png', 'assets/atlas/megaset-1.json');
    }

    create ()
    {
        this.add.image(400, 200, 'atlas', 'titan-mech');
        this.add.image(400, 400, 'atlas', 'ship');
        this.add.image(400, 600, 'atlas', 'supercars-parsec');
    }
}

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

const game = new Phaser.Game(config);

Подготовка ассетов и загрузка атласа

Перед началом работы нужны два файла: изображение-атлас (например, PNG) и JSON-файл с данными о координатах и размерах каждого спрайта внутри этого изображения. Эти файлы можно сгенерировать с помощью таких инструментов, как TexturePacker или Shoebox.

В методе preload() сцены мы используем this.load.atlas() для загрузки обоих файлов. Первый аргумент — это уникальный ключ атласа, по которому мы будем к нему обращаться. Второй и третий аргументы — пути к файлам изображения и данных соответственно.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.atlas('atlas', 'assets/atlas/megaset-1.png', 'assets/atlas/megaset-1.json');
}

Здесь также используется this.load.setBaseURL() для задания базового URL, что позволяет указывать относительные пути для ассетов. После выполнения этого метода Phaser загрузит атлас и распарсит JSON, создав внутреннюю карту всех кадров.

Отображение кадров из атласа на сцене

После загрузки атласа в методе create() мы можем создавать изображения, используя конкретные кадры из него. Для этого используется перегруженный метод this.add.image(x, y, textureKey, frameKey).

- `xиy` — координаты центра изображения на экране. - textureKey — ключ атласа, который мы указали при загрузке (в нашем случае 'atlas'). - frameKey — строковый ключ конкретного спрайта внутри атласа. Этот ключ должен соответствовать имени, указанному в JSON-файле атласа.

create ()
{
    this.add.image(400, 200, 'atlas', 'titan-mech');
    this.add.image(400, 400, 'atlas', 'ship');
    this.add.image(400, 600, 'atlas', 'supercars-parsec');
}

В примере мы размещаем три разных спрайта ('titan-mech', 'ship', 'supercars-parsec') из одного атласа в разных позициях по вертикали. Phaser автоматически находит границы каждого кадра в атласе и отрисовывает только нужную часть изображения.

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

Как и в любом проекте на Phaser, нам нужна базовая конфигурация игры. В объекте config мы указываем тип рендерера, элемент-контейнер на странице и стартовую сцену. Затем создаем экземпляр игры new Phaser.Game(config), который автоматически запускает жизненный цикл сцены (preload, create, update).

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

const game = new Phaser.Game(config);

Ключ type: Phaser.AUTO позволяет Phaser самому выбрать оптимальный рендерер (WebGL или Canvas). parent — это id HTML-элемента, в который будет встроен canvas игры. Класс Example, который мы определили ранее, передается как стартовая сцена.

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

1. **Проверка ключей кадров**: Если спрайт не появляется на сцене, первым делом убедитесь, что ключ кадра (frameKey) точно совпадает с именем в JSON-файле атласа. Регистр символов имеет значение. 2. **Использование загрузчика**: Метод this.load.atlas() является частью системы загрузки Phaser. Все ассеты, загруженные в preload(), становятся доступны только после того, как сцена перейдет в состояние create(). 3. **Доступ к списку кадров**: После загрузки вы можете получить текстуру и проверить список всех доступных кадров через кэш текстур:

// В методе create() или после него
const texture = this.textures.get('atlas');
const frameNames = texture.getFrameNames();
console.log(frameNames); // Выведет массив всех ключей кадров в атласе

4. **Оптимизация**: Объединяйте в один атлас спрайты, которые используются на одном уровне или в одной механике игры, чтобы минимизировать переключения текстур (texture swaps) во время рендеринга.

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

Работа с текстурными атласами в Phaser проста и эффективна. Всего два метода — load.atlas() для загрузки и add.image() с указанием ключа кадра — позволяют организовать ваши графические ресурсы и повысить производительность игры. Для экспериментов попробуйте: - Анимировать спрайты, используя кадры из атласа с помощью this.anims.create(). - Создать несколько атласов для разных уровней игры и динамически их подгружать. - Реализовать систему подсказок, которая выводит в консоль все доступные ключи кадров из загруженного атласа.