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

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

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


var FilePackObject = {
    "pack": {
        "files": [
            {
                "type": "texture",
                "key": "labs",
                "url": {
                    "ASTC": "assets/compressed/compressed/labs-ASTC-4x4-lRGB.pvr",
                    "ETC": "assets/compressed/compressed/labs-ETC2-lRGB.pvr",
                    "PVRTC": "assets/compressed/compressed/labs-PVRTC-4BPP-lRGB.pvr",
                    "S3TC": "assets/compressed/compressed/labs-S3TC-BC3-lRGB.pvr",
                    "IMG": "assets/compressed/uncompressed/labs.png"
                }
            }
        ]
    },
    "meta": {
        "generated": "1401380327373",
        "app": "Phaser 3 Asset Packer",
        "url": "https://phaser.io",
        "version": "1.0",
        "copyright": "Photon Storm Ltd. 2021"
    }
};

class Demo extends Phaser.Scene
{
    constructor ()
    {
        super();
    }

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.pack('pack1', FilePackObject);
    }

    create ()
    {
        const logo = this.add.image(400, 300, 'labs');

        this.add.text(400, 570, logo.frame.source.compressionAlgorithm).setOrigin(0.5, 0);
    }
}

const config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    backgroundColor: '#2d2d6d',
    scene: Demo
};

const game = new Phaser.Game(config);

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

Стандартные форматы изображений вроде PNG или JPEG не всегда эффективны для хранения игровых текстур. Специальные форматы сжатия текстур, такие как ASTC, ETC2, PVRTC и S3TC (BC3), разработаны для аппаратного ускорения на GPU. Они позволяют хранить текстуры в памяти видеокарты в сжатом виде, что экономит как место на диске (ускоряя загрузку), так и видеопамять (VRAM), повышая производительность.

Phaser 3 может автоматически определить, какой из этих форматов поддерживает браузер и устройство игрока, и загрузить наиболее подходящую версию текстуры. Для этого используется специальная структура данных — Asset Pack.

Структура Asset Pack для сжатых текстур

Ключевой элемент в примере — объект FilePackObject. Это JSON-объект, описывающий пакет ассетов. Внутри него для текстуры с ключом 'labs' указано несколько URL-адресов, каждый для своего формата сжатия, а также резервный вариант в формате PNG.

var FilePackObject = {
    "pack": {
        "files": [
            {
                "type": "texture",
                "key": "labs",
                "url": {
                    "ASTC": "assets/compressed/compressed/labs-ASTC-4x4-lRGB.pvr",
                    "ETC": "assets/compressed/compressed/labs-ETC2-lRGB.pvr",
                    "PVRTC": "assets/compressed/compressed/labs-PVRTC-4BPP-lRGB.pvr",
                    "S3TC": "assets/compressed/compressed/labs-S3TC-BC3-lRGB.pvr",
                    "IMG": "assets/compressed/uncompressed/labs.png"
                }
            }
        ]
    },
    "meta": { ... }
};

Phaser анализирует этот объект и загружает только один файл — тот формат, который оптимален для текущего окружения. Свойство 'IMG' служит резервным вариантом на случай, если браузер не поддерживает ни один аппаратный формат.

Загрузка пакета в сцене

Загрузка происходит в методе preload() сцены. Сначала задается базовый URL для всех последующих загрузок с помощью this.load.setBaseURL(). Затем вызывается this.load.pack(), который принимает ключ для этого пакета ('pack1') и сам объект с описанием.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.pack('pack1', FilePackObject);
}

Важно: объект FilePackObject можно загружать и из внешнего JSON-файла, что более практично для больших проектов. В данном же примере он определен прямо в коде.

Использование текстуры и определение формата

После загрузки текстуру можно использовать по её ключу, как и любую другую. В методе create() мы добавляем изображение и текст. Текст отображает алгоритм сжатия, который был фактически использован для этой текстуры.

create ()
{
    const logo = this.add.image(400, 300, 'labs');
    this.add.text(400, 570, logo.frame.source.compressionAlgorithm).setOrigin(0.5, 0);
}

Здесь logo.frame.source.compressionAlgorithm — это свойство, добавленное Phaser, которое содержит строку с названием использованного алгоритма сжатия (например, 'PVRTC' или 'ASTC'). Это полезно для отладки и понимания, какой формат был выбран на конкретном устройстве.

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

Использование сжатых текстур через Asset Pack — это профессиональный подход к оптимизации загрузки и производительности игры в Phaser 3. Система автоматического выбора формата избавляет разработчика от необходимости писать сложную логику определения поддержки браузером. Для экспериментов попробуйте

  1. создать собственные текстуры в разных сжатых форматах с помощью инструментов вроде Texture Packer
  2. загружать описание пакета из внешнего JSON-файла
  3. проверить, какие форматы выбираются на разных устройствах и в разных браузерах, выводя compressionAlgorithm на экран