О чем этот пример
В 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-файл.
