О чем этот пример
При разработке игр под браузер важно не только качество графики, но и скорость загрузки контента. Phaser 3 предоставляет мощный инструмент для загрузки текстур — `load.texture()`, который позволяет автоматически выбирать оптимальный формат изображения в зависимости от поддержки браузером. Этот подход значительно сокращает размер загружаемых файлов и повышает производительность, особенно на мобильных устройствах. В этой статье мы разберем практический пример загрузки сжатого мультиатласа текстур, который подключает разные форматы (ASTC, ETC, PVRTC, S3TC) и автоматически выбирает подходящий. Вы узнаете, как настроить такую систему в своем проекте и какие преимущества она дает.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Demo extends Phaser.Scene
{
constructor ()
{
super();
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
const path = 'assets/compressed';
this.load.texture('test', {
'ASTC': { type: 'PVR', multiAtlasURL: `${path}/uncompressed/multi-ASTC-4x4-lRGB.json`, multiPath: `${path}/compressed` },
'ETC': { type: 'PVR', multiAtlasURL: `${path}/uncompressed/multi-ETC2-lRGB.json`, multiPath: `${path}/compressed` },
'PVRTC': { type: 'PVR', multiAtlasURL: `${path}/uncompressed/multi-PVRTC-4BPP-lRGB.json`, multiPath: `${path}/compressed` },
'S3TC': { type: 'PVR', multiAtlasURL: `${path}/uncompressed/multi-S3TC-BC3-lRGB.json`, multiPath: `${path}/compressed` },
'IMG': { multiAtlasURL: `${path}/uncompressed/multi.json`, multiPath: `${path}/uncompressed/multi.json` }
});
}
create ()
{
this.add.sprite(400, 250, 'test', 'phaser3-logo-x2');
this.add.sprite(400, 100, 'test', 'astorm-truck');
this.add.sprite(400, 420, 'test', 'bunny');
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#2d2d6d',
scene: Demo
};
const game = new Phaser.Game(config);
Что такое мультиатлас и зачем нужна компрессия
Мультиатлас — это набор нескольких текстур (спрайтов), объединенных в один большой файл изображения и описанный в JSON-файле. Такой подход уменьшает количество HTTP-запросов и оптимизирует рендеринг.
Сжатые текстуры (ASTC, ETC, PVRTC, S3TC) — это форматы, которые уменьшают объем видеопамяти (VRAM), занимаемый графикой. Они особенно важны для мобильных устройств и веб-игр, где ресурсы ограничены. Phaser позволяет загружать несколько вариантов одного атласа, каждый в своем формате, и автоматически выбирать тот, который поддерживается браузером пользователя.
this.load.texture('test', {
'ASTC': { type: 'PVR', multiAtlasURL: `${path}/uncompressed/multi-ASTC-4x4-lRGB.json`, multiPath: `${path}/compressed` },
'ETC': { type: 'PVR', multiAtlasURL: `${path}/uncompressed/multi-ETC2-lRGB.json`, multiPath: `${path}/compressed` }
});
Настройка загрузки в методе preload
В методе preload() сценария мы настраиваем базовый URL для загрузки ресурсов и определяем конфигурацию для ключа 'test'. Объект конфигурации содержит свойства, имена которых соответствуют форматам текстур ('ASTC', 'ETC', 'PVRTC', 'S3TC', 'IMG'). Каждое свойство — это объект с параметрами загрузки.
Ключевые параметры:
- type: указывает тип текстуры (например, 'PVR' для форматов, использующих технологию PVR).
- multiAtlasURL: путь к JSON-файлу, который описывает мультиатлас (содержит координаты и размеры каждого спрайта).
- multiPath: базовый путь к самим изображениям (файлам .pvr или .png).
Формат 'IMG' используется как fallback — это обычный PNG-атлас, который будет загружен, если браузер не поддерживает ни один из сжатых форматов.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
const path = 'assets/compressed';
this.load.texture('test', {
'ASTC': { type: 'PVR', multiAtlasURL: `${path}/uncompressed/multi-ASTC-4x4-lRGB.json`, multiPath: `${path}/compressed` },
'ETC': { type: 'PVR', multiAtlasURL: `${path}/uncompressed/multi-ETC2-lRGB.json`, multiPath: `${path}/compressed` },
'PVRTC': { type: 'PVR', multiAtlasURL: `${path}/uncompressed/multi-PVRTC-4BPP-lRGB.json`, multiPath: `${path}/compressed` },
'S3TC': { type: 'PVR', multiAtlasURL: `${path}/uncompressed/multi-S3TC-BC3-lRGB.json`, multiPath: `${path}/compressed` },
'IMG': { multiAtlasURL: `${path}/uncompressed/multi.json`, multiPath: `${path}/uncompressed/multi.json` }
});
}
Использование загруженных текстур в create
После успешной загрузки текстуру можно использовать по ее ключу 'test'. В методе create() мы создаем три спрайта, обращаясь к одному и тому же атласу, но указывая разные имена кадров (frames). Phaser автоматически выберет правильный источник (сжатый или несжатый) на основе возможностей системы.
- 'phaser3-logo-x2', 'astorm-truck', 'bunny' — это имена отдельных спрайтов внутри мультиатласа, которые были определены в JSON-файле.
- this.add.sprite(400, 250, 'test', 'phaser3-logo-x2') создает спрайт в координатах (400, 250), используя текстуру 'test' и кадр 'phaser3-logo-x2'.
create ()
{
this.add.sprite(400, 250, 'test', 'phaser3-logo-x2');
this.add.sprite(400, 100, 'test', 'astorm-truck');
this.add.sprite(400, 420, 'test', 'bunny');
}
Конфигурация игры и запуск сцены
Конфигурационный объект игры определяет основные параметры, такие как тип рендерера, размеры холста, фон и главную сцену. В данном примере используется Phaser.AUTO для автоматического выбора между WebGL и Canvas.
- parent: 'phaser-example' указывает ID HTML-элемента, в который будет встроен canvas игры.
- width и height задают размеры области отрисовки.
- backgroundColor устанавливает цвет фона сцены в шестнадцатеричном формате.
- scene: Demo передает класс нашей сцены, которая будет запущена сразу после инициализации игры.
Создание экземпляра Phaser.Game с этой конфигурацией запускает весь процесс.
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#2d2d6d',
scene: Demo
};
const game = new Phaser.Game(config);
Практические советы по использованию
1. **Подготовка текстур**: Для генерации сжатых мультиатласов используйте инструменты вроде TexturePacker или shoebox. Убедитесь, что вы экспортируете атласы во всех необходимых форматах и создаете JSON-файлы с корректными путями.
2. **Структура папок**: В примере папка assets/compressed содержит подпапки compressed (для сжатых .pvr файлов) и uncompressed (для JSON-описаний и PNG-атласа). Поддерживайте четкую структуру, чтобы пути в коде оставались простыми.
3. **Fallback стратегия**: Всегда включайте вариант 'IMG' с обычными PNG. Это гарантирует, что игра будет работать даже в старых браузерах, пусть и с большим объемом загрузки.
4. **Отладка**: Чтобы проверить, какой формат был загружен, используйте console.log(this.textures.get('test').source[0].compression) после create().
// Пример проверки загруженного формата
create ()
{
const texture = this.textures.get('test');
console.log(texture.source[0].compression); // Выведет 'ASTC', 'ETC' и т.д.
}
Что попробовать дальше
Использование load.texture() с поддержкой нескольких сжатых форматов — это профессиональный подход к управлению графикой в Phaser. Он позволяет значительно сократить время загрузки и потребление памяти без ущерба для качества. Вы можете экспериментировать с добавлением новых форматов (например, Basis Universal) или настроить динамический выбор текстур в зависимости от типа устройства. Попробуйте интегрировать эту систему в свой проект и измерьте прирост производительности на мобильных устройствах.
