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

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

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

Живой запуск

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

Исходный код


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

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.atlas('fontatlas', 'assets/atlas/bitmap-fonts-debug.png', 'assets/atlas/bitmap-fonts.json');

        //  The XML data for the fonts in the atlas
        this.load.xml('atariXML', 'assets/fonts/bitmap/atari-sunset.xml');
        this.load.xml('azoXML', 'assets/fonts/bitmap/azo-fire.xml');
        this.load.xml('hyperdriveXML', 'assets/fonts/bitmap/hyperdrive.xml');
        this.load.xml('topazXML', 'assets/fonts/bitmap/topaz-fill.xml');
    }

    create ()
    {
        //  Create a new Bitmap Text in the Cache from the given atlas frame and XML data
        Phaser.GameObjects.BitmapText.ParseFromAtlas(this, 'font1', 'fontatlas', 'hyperdrive', 'hyperdriveXML');
        Phaser.GameObjects.BitmapText.ParseFromAtlas(this, 'font2', 'fontatlas', 'azo-fire', 'azoXML');
        Phaser.GameObjects.BitmapText.ParseFromAtlas(this, 'font3', 'fontatlas', 'atari-sunset', 'atariXML');
        Phaser.GameObjects.BitmapText.ParseFromAtlas(this, 'font4', 'fontatlas', 'topaz-fill', 'topazXML');

        const str = '()WTRPyxv^}{';

        this.add.bitmapText(0, 100, 'font1', str);
        this.add.bitmapText(0, 200, 'font2', str);
        this.add.bitmapText(0, 300, 'font3', str);
        this.add.bitmapText(0, 400, 'font4', str);
    }
}

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

const game = new Phaser.Game(config);

Загрузка ресурсов: атлас и метаданные

Перед созданием BitmapText необходимо загрузить два ключевых ресурса: атлас текстур (изображение) и XML-файл с метаданными о шрифте. Атлас содержит все глифы (символы) шрифта, а XML описывает их положение, размер и другие свойства.

Загрузка выполняется в методе preload. Метод load.setBaseURL устанавливает базовый URL для удобства. Затем с помощью load.atlas загружается сам атлас. Параметр 'fontatlas' — это ключ для обращения к атласу, далее идут пути к изображению и JSON-файлу с разметкой. JSON описывает, какие кадры (frames) находятся на изображении. Отдельно загружаются XML-файлы для каждого шрифта, используя метод load.xml.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.atlas('fontatlas', 'assets/atlas/bitmap-fonts-debug.png', 'assets/atlas/bitmap-fonts.json');

    //  The XML data for the fonts in the atlas
    this.load.xml('atariXML', 'assets/fonts/bitmap/atari-sunset.xml');
    this.load.xml('azoXML', 'assets/fonts/bitmap/azo-fire.xml');
    this.load.xml('hyperdriveXML', 'assets/fonts/bitmap/hyperdrive.xml');
    this.load.xml('topazXML', 'assets/fonts/bitmap/topaz-fill.xml');
}

Парсинг шрифтов: создание данных в кэше

Загруженные ресурсы — это сырые данные. Чтобы использовать их как шрифт для BitmapText, их нужно скомбинировать и зарегистрировать в кэше игровых объектов. Именно это делает статический метод Phaser.GameObjects.BitmapText.ParseFromAtlas. Он берет кадр из атласа (текстуру с символами) и XML-описание, парсит их и создает новый ключ шрифта в кэше.

Метод принимает следующие аргументы: контекст сцены (this), ключ, под которым новый шрифт будет сохранен в кэше, ключ атласа, имя кадра внутри атласа и ключ загруженного XML-данных. В примере создается четыре различных шрифта из одного атласа.

//  Create a new Bitmap Text in the Cache from the given atlas frame and XML data
Phaser.GameObjects.BitmapText.ParseFromAtlas(this, 'font1', 'fontatlas', 'hyperdrive', 'hyperdriveXML');
Phaser.GameObjects.BitmapText.ParseFromAtlas(this, 'font2', 'fontatlas', 'azo-fire', 'azoXML');
Phaser.GameObjects.BitmapText.ParseFromAtlas(this, 'font3', 'fontatlas', 'atari-sunset', 'atariXML');
Phaser.GameObjects.BitmapText.ParseFromAtlas(this, 'font4', 'fontatlas', 'topaz-fill', 'topazXML');

Создание и отображение текста

После того как шрифты зарегистрированы в кэше, их можно использовать для создания объектов BitmapText. Это делается с помощью фабричного метода this.add.bitmapText. Метод принимает координаты X и Y, ключ шрифта (который мы задали при парсинге) и строку для отображения.

В примере одна и та же тестовая строка выводится четырьмя разными шрифтами, каждый на своей высоте (координата Y). Это наглядно демонстрирует результат работы.

const str = '()WTRPyxv^}{';

this.add.bitmapText(0, 100, 'font1', str);
this.add.bitmapText(0, 200, 'font2', str);
this.add.bitmapText(0, 300, 'font3', str);
this.add.bitmapText(0, 400, 'font4', str);

Преимущества и практическое применение

Использование ParseFromAtlas дает несколько преимуществ: 1. **Оптимизация загрузки:** Все глифы для нескольких шрифтов упакованы в один атлас (одно изображение), что уменьшает количество HTTP-запросов. 2. **Гибкость:** Вы можете хранить множество альтернативных пиксельных шрифтов в одном проекте, переключаясь между ними по ключу. 3. **Производительность:** Отрисовка BitmapText из текстуры обычно быстрее, чем рендеринг векторных шрифтов через Canvas или WebGL.

Этот подход идеально подходит для статического или редко меняющегося текста в интерфейсе (очки, названия, лейблы), особенно в играх с пиксельной графикой, где требуется точное соответствие визуальному стилю.

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

Метод Phaser.GameObjects.BitmapText.ParseFromAtlas открывает удобный способ работы с пиксельными шрифтами, объединяя эффективность атласов текстур и гибкость XML-описаний. Для экспериментов попробуйте: создать собственный атлас из нескольких шрифтов с помощью инструментов вроде TexturePacker; анимировать текст, меняя ключ шрифта на лету для эффекта «глитча»; или использовать разные шрифта для разных языков в локализации, подгружая нужный XML-файл.