О чем этот пример
Визуальные эффекты для текста — простой способ повысить привлекательность игры. Статичные надписи скучны, а плавные цветовые переходы оживляют интерфейс, меню или титры. В этом примере показано, как создать динамически окрашенный текст с градиентом, используя встроенные возможности Phaser 3 для работы с Bitmap-шрифтами и кастомным рендерингом. Вы научитесь применять callback-функцию для тонирования каждого символа в реальном времени, что открывает путь к созданию мерцающих, переливающихся или реагирующих на игровые события текстовых элементов.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
let i = 0;
let hsv = [];
class Example extends Phaser.Scene
{
constructor ()
{
super();
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.bitmapFont('ice', 'assets/fonts/bitmap/iceicebaby.png', 'assets/fonts/bitmap/iceicebaby.xml');
}
create ()
{
hsv = Phaser.Display.Color.HSVColorWheel();
const tintedText = this.add.dynamicBitmapText(32, 64, 'ice', '- Phaser III -', 128);
tintedText.setDisplayCallback(this.textCallback);
}
textCallback (data)
{
data.tint.topLeft = hsv[Math.floor(i)].color;
data.tint.topRight = hsv[359 - Math.floor(i)].color;
data.tint.bottomLeft = hsv[359 - Math.floor(i)].color;
data.tint.bottomRight = hsv[Math.floor(i)].color;
i += 0.05;
if (i >= hsv.length)
{
i = 0;
}
return data;
}
}
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
backgroundColor: '#2d2d2d',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка: загрузка Bitmap-шрифта
Bitmap-шрифты в Phaser — это предварительно отрендеренные изображения символов. Они обеспечивают чёткое отображение и высокую производительность, так как не требуют загрузки системных шрифтов. В методе preload мы указываем базовый URL для ресурсов и загружаем файлы шрифта: изображение (PNG) и файл описания (XML), который содержит данные о расположении каждого символа на изображении.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.bitmapFont('ice', 'assets/fonts/bitmap/iceicebaby.png', 'assets/fonts/bitmap/iceicebaby.xml');
}
Создание динамического текстового объекта
В методе create мы инициализируем наш текст. Ключевой объект здесь — DynamicBitmapText. В отличие от статичного, он позволяет модифицировать свойства каждого символа (глифа) на лету через callback-функцию. Мы создаём объект, указываем позицию, ключ загруженного шрифта, строку для отображения и размер.
create ()
{
hsv = Phaser.Display.Color.HSVColorWheel();
const tintedText = this.add.dynamicBitmapText(32, 64, 'ice', '- Phaser III -', 128);
tintedText.setDisplayCallback(this.textCallback);
}
Перед этим мы генерируем палитру цветов с помощью Phaser.Display.Color.HSVColorWheel(). Этот метод возвращает массив из 360 объектов цвета, представляющих полный цветовой круг в модели HSV (оттенок, насыщенность, значение). Это даёт нам плавный градиент для анимации.
Магия callback-функции: тонирование символов
Сердце эффекта — функция textCallback. Она вызывается для каждого символа текста при каждом обновлении кадра (рендере). В параметр data передаётся объект с информацией о символе: его индекс, позиция на холсте и, что важно для нас, объект tint.
textCallback (data)
{
data.tint.topLeft = hsv[Math.floor(i)].color;
data.tint.topRight = hsv[359 - Math.floor(i)].color;
data.tint.bottomLeft = hsv[359 - Math.floor(i)].color;
data.tint.bottomRight = hsv[Math.floor(i)].color;
i += 0.05;
if (i >= hsv.length)
{
i = 0;
}
return data;
}
Объект tint содержит четыре свойства, соответствующие углам символа: topLeft, topRight, bottomLeft, bottomRight. Каждому из них мы присваиваем цвет из нашей HSV-палитры. Используя глобальную переменную `iи её зеркальное отражение359 - Math.floor(i), мы задаём разные цвета для противоположных углов, создавая диагональный градиент. Плавное увеличениеi` на каждом вызове функции анимирует этот градиент, заставляя цвета «перетекать» по тексту.
Конфигурация игры и запуск
Сцена готова, остаётся собрать конфигурацию игры и запустить её. В этом примере используется WEBGL-рендерер для лучшей производительности графических эффектов.
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
backgroundColor: '#2d2d2d',
scene: Example
};
const game = new Phaser.Game(config);
Указав тёмно-серый фон, мы обеспечиваем хороший контраст для яркого переливающегося текста.
Что попробовать дальше
Динамические Bitmap-тексты в Phaser 3 — мощный инструмент для кастомного рендеринга. Вы освоили создание анимированного цветового градиента с помощью setDisplayCallback. Для экспериментов попробуйте изменить логику в callback-функции: привяжите цвет не к глобальному счётчику, а к позиции символа data.index для статичного радужного текста; используйте Math.sin() для пульсирующего эффекта; или меняйте не только tint, но и alpha (прозрачность) для мерцания. Это открывает двери к созданию уникальных визуальных подписей для ваших игровых проектов.
