О чем этот пример
Вы когда-нибудь задумывались, как создавать плавно вращающийся текст или сложные динамические эффекты для UI, не нагружая производительность? Обычный текст в Phaser, хоть и удобен, может стать узким местом при рендеринге сложных анимаций каждый кадр. Решение — использовать Render Texture. Эта статья покажет, как «печатать» текстовый объект на динамическую текстуру (Render Texture) и анимировать уже саму текстуру. Этот подход позволяет один раз отрендерить сложный текст (со шрифтами, стилями, переносами строк) и затем манипулировать им как единым, легковесным изображением, что идеально для счетчиков, титров или эффектных заставок.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
text;
rt;
create ()
{
this.text = this.add.text(0, 0, 'Hello from a\nRender Texture').setFontSize(48);
this.text.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.text, 400, 300);
this.rt.render();
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Что такое Render Texture и зачем она нужна для текста?
Render Texture — это особый тип игрового объекта в Phaser, который представляет собой динамическое изображение (текстуру), на которое можно рисовать другие объекты. Вы можете думать о ней как о холсте или буфере в памяти.
Ключевая выгода при работе с текстом в следующем: вместо того чтобы перерисовывать и трансформировать (вращать, масштабировать) сложный текстовый объект каждый кадр, мы рисуем его на Render Texture один раз (или по необходимости), а затем анимируем уже саму текстуру. Рендеринг текста — операция ресурсоемкая для GPU, особенно для шрифтов с обводкой или тенями. С Render Texture эта операция выполняется реже, а дешевая трансформация текстуры (поворот, сдвиг) — каждый кадр.
В нашем примере мы создадим текстовый объект, скроем его, а его «отпечаток» будем вращать на Render Texture.
Подготовка сцены: создание текста и Render Texture
Вся логика размещается в методах класса сцены. В create() мы инициализируем объекты, которые не будут меняться со временем.
Сначала создается обычный текстовый объект с помощью this.add.text(). Мы позиционируем его в точке (0, 0), но это не важно, так как позже мы будем рисовать его в конкретных координатах на текстуре. Обратите внимание на перенос строки \n в строке текста — Render Texture корректно отобразит многострочный контент.
Сразу после создания мы делаем оригинальный текст невидимым (setVisible(false)). Он нам нужен только как источник данных для отрисовки, но не должен отображаться на сцене самостоятельно.
Затем создается сама Render Texture. Важно понять ее параметры: это координаты ее размещения на сцене (400, 300), а также ее ширина и высота (800, 600). Это размеры *холста* текстуры, на котором мы будем рисовать.
create ()
{
this.text = this.add.text(0, 0, 'Hello from a\nRender Texture').setFontSize(48);
this.text.setVisible(false);
this.rt = this.add.renderTexture(400, 300, 800, 600);
}
Анимация в update(): цикл очистки, рисования и рендера
Вся магия происходит в методе update(), который вызывается на каждом кадре игры. Здесь выполняется последовательность действий для анимирования текста на текстуре.
1. **Вращение камеры текстуры:** this.rt.camera.rotation -= 0.01;
У каждой Render Texture есть своя собственная камера. Вращая ее, мы вращаем весь *вид* на содержимое текстуры. Это создает эффект вращения нарисованного текста.
2. **Очистка текстуры:** this.rt.clear();
Этот метод полностью очищает холст Render Texture, заливая его прозрачным цветом. Если его не вызвать, предыдущие кадры будут накапливаться, создавая эффект шлейфа. Для плавной анимации очистка необходима каждый кадр.
3. **Рисование текста:** this.rt.draw(this.text, 400, 300);
Вот ключевой момент. Метод draw() «штампует» переданный игровой объект (наш скрытый текст) на Render Texture. Координаты (400, 300) — это точка *на холсте текстуры*, куда будет помещен центр текстового объекта. Поскольку размеры текстуры тоже 800x600, мы размещаем текст точно по ее центру.
4. **Финализация рендера:** this.rt.render();
Этот метод явно указывает текстуре, что нужно обновить свое внутреннее состояние и отображение на сцене после всех операций рисования. В простых случаях (один вызов draw) он может работать и без него, но для сложных сценариев и гарантии корректного отображения его рекомендуется вызывать.
update ()
{
// Вращаем вид камеры Render Texture
this.rt.camera.rotation -= 0.01;
// Очищаем текстуру от предыдущего кадра
this.rt.clear();
// Рисуем текстовый объект в центре холста текстуры
this.rt.draw(this.text, 400, 300);
// Применяем все изменения
this.rt.render();
}
Конфигурация игры и запуск
Код примера завершается стандартной для Phaser 3 конфигурацией игры. В ней указывается тип рендерера, контейнер в DOM, размеры холста и стартовая сцена — наш класс Example.
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Render Texture — мощный инструмент для оптимизации и создания эффектов. Вместо вращения дорогого текстового объекта мы вращаем легковесную текстуру. Для экспериментов попробуйте
- Рисовать на одну текстуру несколько текстовых объектов с разными позициями
- Менять не
camera.rotation, аcamera.zoomдля эффекта приближения - Вызывать
draw()не каждый кадр, а только при изменении текста (для счетчика очков), что даст максимальный прирост производительности - Использовать
rt.saveTexture('key')для сохранения результата в текстуру кэша и повторного использования
