О чем этот пример
Использование bitmap-шрифтов — отличный способ добавить в игру стилизованный текст, который будет выглядеть одинаково на всех устройствах. В этой статье мы разберем, как загружать несколько таких шрифтов из единого JSON-пака, управлять их отображением и создавать динамически обновляемый текст, например, для счетчиков очков или таймеров. Это упрощает организацию ресурсов и ускоряет разработку.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
dynamic = null;
value = 0;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.pack('pack', 'assets/loader-tests/pack6.json');
}
create ()
{
this.add.bitmapText(0, 0, 'desyrel', 'Lorem ipsum\ndolor sit amet');
this.add.bitmapText(0, 200, 'desyrel-pink', 'Excepteur sint occaecat\ncupidatat non proident');
this.add.bitmapText(0, 400, 'shortStack', 'Phaser BitmapText');
this.dynamic = this.add.bitmapText(0, 500, 'desyrel', '');
}
update ()
{
this.dynamic.text = `value: ${this.value.toFixed(2)}`;
this.value += 0.01;
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Загрузка ресурсов через JSON-пак
Вместо того чтобы загружать каждый шрифт по отдельности, Phaser позволяет использовать JSON-пак — файл-манифест, описывающий несколько ресурсов. Это удобно для структурирования.
В методе preload() мы настраиваем базовый URL и загружаем пак с помощью load.pack().
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.pack('pack', 'assets/loader-tests/pack6.json');
}
Ключ 'pack' — это внутренний идентификатор загрузки, а второй аргумент — путь к JSON-файлу. Содержимое этого файла определяет, какие именно шрифты (изображения и XML/JSON данные) будут загружены.
Создание статического bitmap-текста
После загрузки ресурсов в методе create() мы можем создавать текстовые объекты. Bitmap-текст создается методом add.bitmapText(), который принимает координаты X, Y, ключ шрифта и строку для отображения.
create ()
{
this.add.bitmapText(0, 0, 'desyrel', 'Lorem ipsum\ndolor sit amet');
this.add.bitmapText(0, 200, 'desyrel-pink', 'Excepteur sint occaecat\ncupidatat non proident');
this.add.bitmapText(0, 400, 'shortStack', 'Phaser BitmapText');
this.dynamic = this.add.bitmapText(0, 500, 'desyrel', '');
}
Ключи шрифтов ('desyrel', 'desyrel-pink', 'shortStack') должны соответствовать тем, что объявлены в загруженном паке. Обратите внимание на использование \n для переноса строки — bitmap-шрифты это поддерживают. Последний объект мы сохраняем в свойство сцены this.dynamic для дальнейшего обновления.
Динамическое обновление текста
Основное преимущество bitmap-текста в Phaser — возможность менять его строку на лету без пересоздания объекта. Это идеально для значений, которые часто меняются.
В методе update(), который вызывается каждый кадр, мы обновляем свойство .text нашего сохраненного объекта.
update ()
{
this.dynamic.text = `value: ${this.value.toFixed(2)}`;
this.value += 0.01;
}
Мы используем шаблонную строку для форматирования, а метод toFixed(2) округляет число this.value до двух знаков после запятой. Инкремент this.value на 0.01 каждый кадр создает плавно увеличивающееся число. Таким образом можно отображать здоровье, очки, время или прогресс.
Конфигурация игры и запуск
Как и в любом проекте Phaser, нам нужна базовая конфигурация игры. В ней мы указываем тип рендерера, родительский контейнер в DOM и стартовую сцену.
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Phaser.AUTO автоматически выбирает между WebGL и Canvas рендерингом. Свойство parent должно соответствовать id HTML-элемента, в который будет встроена игра. Класс Example, который мы разобрали, передается как стартовая сцена.
Что попробовать дальше
Использование JSON-паков для загрузки bitmap-шрифтов делает код чище, а управление ресурсами — централизованным. Динамическое обновление текста открывает широкие возможности для игрового интерфейса. Для экспериментов попробуйте: изменить скорость инкремента this.value, добавить второй динамический счетчик с другим шрифтом, или анимировать положение текста, изменяя свойства this.dynamic.x и this.dynamic.y внутри update().
