О чем этот пример
Render Texture (текстура для отрисовки) в Phaser — это мощный инструмент для создания динамических изображений прямо во время выполнения игры. В отличие от статичных картинок, загруженных из файлов, Render Texture позволяет комбинировать несколько игровых объектов в одну новую текстуру, которую затем можно использовать как спрайт, тайл или фон. Это особенно полезно для генерации уникальных визуальных эффектов, интерфейсов, кастомизации персонажей или оптимизации отрисовки сложных составных объектов.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bubble', 'assets/particles/bubble.png');
this.load.image('dude', 'assets/sprites/phaser-dude.png');
}
create ()
{
const bubble = this.add.image(0, 0, 'bubble');
const dude = this.add.image(0, 0, 'dude');
const rt = this.add.renderTexture(400, 300, 64, 64);
rt.draw(bubble, 32, 32);
rt.draw(dude, 32, 32);
rt.render();
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#2d2d88',
scene: Example
};
const game = new Phaser.Game(config);
Что такое Render Texture?
RenderTexture — это специальный игровой объект, который представляет собой холст в памяти. Вы можете "рисовать" на нём другие игровые объекты (спрайты, изображения, текст) с помощью метода draw(). После отрисовки RenderTexture сама становится источником текстуры, которую можно использовать где угодно, например, как изображение для спрайта.
Ключевое преимущество — производительность. Если у вас есть сложная композиция из десятков мелких спрайтов, которые редко меняются, отрисовка их один раз в RenderTexture, а затем использование этой текстуры как единого объекта, значительно снижает нагрузку на рендерер.
Разбор примера кода: от загрузки до создания
Давайте пройдемся по ключевым шагам примера.
Сначала в методе preload загружаются два изображения: пузырёк (bubble) и персонаж (dude). Они будут исходными "кирпичиками" для нашей новой текстуры.
this.load.image('bubble', 'assets/particles/bubble.png');
this.load.image('dude', 'assets/sprites/phaser-dude.png');
В методе create создаются два игровых объекта Image на основе загруженных текстур. Обратите внимание, их позиция (0, 0) не важна для сцены, так как мы будем использовать их только как источник для отрисовки.
const bubble = this.add.image(0, 0, 'bubble');
const dude = this.add.image(0, 0, 'dude');
Затем создается сама RenderTexture. Её конструктор принимает координаты (x, y) для размещения на сцене и размеры (width, height).
const rt = this.add.renderTexture(400, 300, 64, 64);
Метод draw() и финализация
Сердце процесса — метод draw() объекта RenderTexture. Он принимает игровой объект и координаты *относительно левого верхнего угла самой RenderTexture*, куда этот объект будет нарисован.
В нашем примере мы рисуем сначала пузырёк, а затем персонажа в одну и ту же точку (32, 32). Так как RenderTexture имеет размер 64x64, точка (32, 32) — это её центр.
rt.draw(bubble, 32, 32);
rt.draw(dude, 32, 32);
Персонаж будет нарисован поверх пузырька. Порядок вызовов draw() имеет значение, как и в обычном 2D-холсте: последний нарисованный объект оказывается сверху.
Хотя в данном примере это не критично, метод render() явно сообщает движку, что отрисовка в текстуру завершена. Это может быть полезно для оптимизации, если вы планируете многократно перерисовывать текстуру.
rt.render();
В результате на сцене по координатам (400, 300) появится квадратное изображение размером 64x64, в центре которого будет наложенное изображение персонажа на пузырёк.
Практическое применение и вариации
Рассмотрим, как можно расширить этот простой пример для решения реальных игровых задач.
**1. Создание составного спрайта:** Вы можете нарисовать в одну RenderTexture базовое тело персонажа, затем отдельно — броню, оружие и шлем. Получится кастомизируемый персонаж.
**2. Кэширование сложной сцены:** Если у вас статичный фон, составленный из множества декораций, отрисуйте его один раз в большую RenderTexture и используйте её как фон. Это снизит количество объектов на сцене.
**3. Создание снарядов или эффектов:** Сгенерируйте текстуру для снаряда, динамически добавив на базовое изображение эффект огня или льда.
// Пример: Отрисовка текста на текстуре
const rt = this.add.renderTexture(100, 100, 200, 50);
const basePanel = this.add.rectangle(0, 0, 200, 50, 0x333333);
const text = this.add.text(0, 0, 'Уровень 10', { fontFamily: 'Arial', fontSize: 24 });
rt.draw(basePanel, 100, 25); // Центрируем панель
rt.draw(text, 100, 25); // Центрируем текст
rt.render();
**Важно:** Объекты, которые вы рисуете (bubble, dude), не обязательно должны быть видимы на сцене. Их можно создавать временно, только для передачи в draw().
Что попробовать дальше
RenderTexture открывает путь к динамическому созданию контента в Phaser, что незаменимо для игр с процедурной генерацией, глубокой кастомизацией или требовательных к производительности. Поэкспериментируйте: попробуйте анимировать исходные спрайты перед отрисовкой, используйте RenderTexture как маску или рисуйте в неё с разными режимами смешивания (blendMode). Это мощный инструмент, который переносит логику создания графики из редакторов прямо в ваш игровой код.
