О чем этот пример
Render Texture (текстура для рендеринга) — это мощный инструмент в Phaser, который позволяет рисовать на динамическом холсте прямо во время выполнения игры. В отличие от статичных изображений, Render Texture можно изменять в реальном времени, что открывает возможности для создания интерактивных элементов: рисования игроком, спецэффектов, динамических масок или пользовательских интерфейсов. В этой статье мы разберем конкретный пример, где игрок может рисовать цветной кистью по экрану. Вы узнаете, как создать Render Texture, работать с событиями ввода и использовать цветовую палитру HSV для создания плавных градиентов.
Версия 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('brush', 'assets/sprites/brush1.png');
}
create ()
{
const rt = this.add.renderTexture(400, 300, 800, 600);
const brush = this.textures.getFrame('brush');
const hsv = Phaser.Display.Color.HSVColorWheel();
let i = 0;
this.input.on('pointermove', pointer =>
{
if (pointer.isDown)
{
rt.draw(brush, pointer.x - 32, pointer.y - 32, 1, hsv[i].color).render();
i++;
if (i === 360)
{
i = 0;
}
}
}, this);
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Создание динамического холста: Render Texture
Первым делом в методе create() создается объект Render Texture. Это специальный игровой объект, который ведет себя как текстура, но ее содержимое можно изменять программно.
const rt = this.add.renderTexture(400, 300, 800, 600);
Здесь rt — это наша текстура для рисования. Аргументы метода: координаты X (400) и Y (300) центра текстуры на сцене, а также ее ширина (800) и высота (600) в пикселях. По сути, мы создали прозрачный холст размером во весь экран (так как конфигурация игры также 800x600) и разместили его по центру.
Подготовка кисти и цветовой палитры
Чтобы рисовать, нужны кисть и краски. Кистью будет спрайт, загруженный в preload(). Мы получаем его кадр (Frame) из менеджера текстур.
const brush = this.textures.getFrame('brush');
Для красок используется встроенный генератор цветового круга HSV (Оттенок, Насыщенность, Яркость). Этот метод возвращает массив из 360 объектов, каждый из которых содержит цвет в числовом формате и другие представления, что соответствует полному кругу оттенков.
const hsv = Phaser.Display.Color.HSVColorWheel();
let i = 0;
Переменная `i` будет служить индексом для выбора текущего цвета из этого массива.
Обработка ввода и рисование на текстуре
Логика рисования привязана к событию перемещения указателя (мыши или касания). Код внутри обработчика срабатывает каждый раз, когда курсор двигается.
this.input.on('pointermove', pointer => {
if (pointer.isDown) {
rt.draw(brush, pointer.x - 32, pointer.y - 32, 1, hsv[i].color).render();
i++;
if (i === 360) {
i = 0;
}
}
}, this);
Ключевой момент — проверка pointer.isDown. Рисование происходит только если кнопка мыши зажата или палец прижат к экрану.
Метод rt.draw() наносит отпечаток кисти (brush) на нашу Render Texture. Аргументы:
1. brush: Источник для рисования (кадр текстуры).
2. pointer.x - 32, pointer.y - 32: Позиция для отрисовки. Вычитание 32 пикселя (половина от размера кисти 64x64) центрирует кисть относительно курсора.
3. `1`: Масштаб отрисовки (1 = оригинальный размер).
4. hsv[i].color: Цветовой тон (tint), который применяется к кисти.
Сразу после draw() вызывается .render(), чтобы изменения сразу отобразились на экране.
После каждого отпечатка индекс `i` увеличивается, и цвет плавно меняется по кругу. Когда индекс достигает 360, он сбрасывается на 0.
Почему именно Render Texture, а не множество спрайтов?
Можно было бы создать новый спрайт кисти при каждом движении мыши. Однако это быстро привело бы к созданию сотен или тысяч игровых объектов, что негативно скажется на производительности.
Render Texture решает эту проблему. Все отпечатки кисти "сливаются" в одну текстуру (один игровой объект). С точки зрения рендеринга, это намного эффективнее. Вы рисуете не объектами, а пикселями на одном холсте. Это классический подход для создания таких эффектов, как рисование, следы или динамически генерируемые карты.
Что попробовать дальше
Render Texture — это ваш динамический холст внутри игры Phaser. В рассмотренном примере мы реализовали интерактивную кисть с меняющимся цветом. Этот механизм лежит в основе множества других техник.
Для экспериментов попробуйте:
1. Изменить кисть на другую текстуру (например, частицу или геометрическую фигуру).
2. Реализовать "ластик", используя метод rt.erase().
3. Сохранять получившееся изображение с помощью rt.snapshot().
4. Использовать rt.drawFrame() для рисования кадров из атласа анимации, создавая анимированные следы.
