О чем этот пример
Render Texture в Phaser 3 — это мощный инструмент для рендеринга игровых объектов в текстуру, с которой затем можно работать как с единым изображением. Это открывает возможности для создания сложных визуальных эффектов, таких как дрожащий текст, частицы или динамические маски, без необходимости обрабатывать каждый объект отдельно на основном канвасе. В этой статье мы разберем практический пример совмещения динамического bitmap-текста с Render Texture для генерации стильного, анимированного заголовка.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
bitmaptext;
rt;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.bitmapFont('desyrel', 'assets/fonts/bitmap/desyrel.png', 'assets/fonts/bitmap/desyrel.xml');
}
create ()
{
this.bitmaptext = this.add.dynamicBitmapText(0, 0, 'desyrel', 'PHASER 3\nRender Texture', 64);
this.bitmaptext.setDisplayCallback(this.textCallback);
this.bitmaptext.setVisible(false);
this.rt = this.add.renderTexture(400, 300, 800, 600);
}
update ()
{
this.rt.camera.rotation -= 0.01;
this.rt.clear();
this.rt.draw(this.bitmaptext, 300, 400);
this.rt.render();
}
textCallback (data)
{
data.x = Phaser.Math.Between(data.x - 2, data.x + 2);
data.y = Phaser.Math.Between(data.y - 4, data.y + 4);
return data;
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и загрузка ресурсов
В методе preload загружается bitmap-шрифт. Важно указать и изображение, и XML-файл с данными о глифах.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.bitmapFont('desyrel', 'assets/fonts/bitmap/desyrel.png', 'assets/fonts/bitmap/desyrel.xml');
}
В методе create инициализируются ключевые объекты. Сначала создается динамический bitmap-текст. Его особенность — возможность изменять свойства каждого символа в реальном времени через callback-функцию.
create ()
{
this.bitmaptext = this.add.dynamicBitmapText(0, 0, 'desyrel', 'PHASER 3\nRender Texture', 64);
this.bitmaptext.setDisplayCallback(this.textCallback);
this.bitmaptext.setVisible(false);
this.rt = this.add.renderTexture(400, 300, 800, 600);
}
Обратите внимание: исходный текст (this.bitmaptext) скрыт методом setVisible(false), потому что он будет отрисовываться не на основную сцену, а внутрь Render Texture.
Магия Render Texture: принцип работы
Render Texture (this.rt) — это, по сути, отдельный канвас или кадровый буфер. В данном примере он создается с центром в точке (400, 300) и размером 800x600 пикселей.
Основная логика анимации происходит в update. Каждый кадр мы:
1. Вращаем камеру самой Render Texture.
2. Очищаем её предыдущее содержимое.
3. Отрисовываем в неё наш динамический текст.
4. Явно вызываем рендеринг.
Этот цикл создает эффект постоянно вращающейся текстуры со статичным относительно неё текстом.
update ()
{
this.rt.camera.rotation -= 0.01;
this.rt.clear();
this.rt.draw(this.bitmaptext, 300, 400);
this.rt.render();
}
Метод draw принимает игровой объект и координаты для отрисовки внутри Render Texture. Здесь текст рисуется в точке (300, 400) относительно центра rt.
Динамическое изменение текста через Callback
Сила DynamicBitmapText раскрывается в функции обратного вызова textCallback. Она выполняется для каждого символа текста перед его отрисовкой, позволяя модифицировать его свойства.
textCallback (data)
{
data.x = Phaser.Math.Between(data.x - 2, data.x + 2);
data.y = Phaser.Math.Between(data.y - 4, data.y + 4);
return data;
}
Функция получает объект data с параметрами символа (координаты, индекс, код и т.д.). В данном примере мы каждый кадр случайным образом смещаем символ по осям X и Y в небольшом диапазоне, используя Phaser.Math.Between. Это создает эффект легкого, хаотичного дрожания («шума») для каждого символа, что добавляет тексту живого, цифрового вида.
Этот callback назначается тексту с помощью setDisplayCallback(this.textCallback).
Конфигурация игры и запуск
Стандартная конфигурация игры Phaser 3. Ключевой момент — указание нашего класса Example в качестве основной сцены.
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Размеры окна игры (800x600) соответствуют размеру созданной Render Texture, что позволяет ей заполнить весь экран.
Что попробовать дальше
Комбинация DynamicBitmapText с Render Texture предоставляет отличный контроль над сложными текстовыми эффектами, изолируя их рендеринг от основного игрового поля. Вы можете экспериментировать: изменять логику в textCallback для масштабирования, окрашивания или поворота символов; анимировать не камеру, а саму Render Texture в пространстве сцены; или рисовать в одну текстуру несколько различных объектов (спрайты, частицы) для создания сложных композитных эффектов.
