О чем этот пример
В игровой разработке производительность напрямую зависит от эффективной загрузки и отрисовки графики. Использование текстурных атласов — стандартный приём для сокращения количества сетевых запросов и 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 или подобной утилите; изменить код, чтобы спрайты появлялись не случайно, а в определённом порядке для создания анимации; или загрузить несколько разных мульти-атласов и переключаться между ними в зависимости от игровой сцены.
