О чем этот пример
Работая с RenderTexture в Phaser, можно столкнуться с неожиданным поведением при отрисовке спрайтов, которым был задан оттенок (tint). Эта статья разбирает тонкости методов `fill()`, `draw()` и взаимодействия объекта спрайта с его текстурами. Понимание этих нюансов поможет избежать визуальных артефактов и даст полный контроль над динамическим рендерингом в вашей игре.
Версия 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('brain', 'assets/sprites/beer.png');
}
create ()
{
const rt = this.add.renderTexture(200, 300, 256, 256);
const sprite = this.add.image(400, 300, 'brain');
sprite.setTint(0xff0000);
rt.fill(0x00ff00);
rt.draw('brain', 0, 0, 1, 0xff0000);
rt.draw(sprite, 128, 128);
}
}
new Phaser.Game({
width: 800,
height: 600,
type: Phaser.WEBGL,
parent: 'phaser-example',
scene: Example
});
Разбираем код примера
В данном примере создаются два графических объекта: RenderTexture (rt) и спрайт (sprite), загруженный из изображения 'brain'. Ключевые действия происходят в методе create().
const rt = this.add.renderTexture(200, 300, 256, 256);
const sprite = this.add.image(400, 300, 'brain');
Сначала создается RenderTexture размером 256x256 пикселей с центром в точке (200, 300). Затем создается обычный спрайт в позиции (400, 300). Далее происходят три операции, влияющие на цвет.
Магия и конфликт оттенков (Tint)
Метод setTint применяет цветовой оттенок ко всему спрайту при его отрисовке на основном холсте игры. Однако это свойство также влияет на исходную текстуру спрайта.
sprite.setTint(0xff0000); // Окрашивает спрайт в красный
rt.fill(0x00ff00); // Заливает всю RenderTexture зеленым
Здесь спрайт становится красным, а RenderTexture заливается сплошным зеленым цветом. Важно понимать, что fill работает именно на целевом RenderTexture, перезаписывая все его пиксели.
Нюансы метода `draw`
Метод draw объекта RenderTexture может принимать для отрисовки как строковый ключ текстуры, так и игровой объект (например, спрайт). Поведение будет разным.
rt.draw('brain', 0, 0, 1, 0xff0000);
rt.draw(sprite, 128, 128);
Первым вызовом мы рисуем оригинальное изображение 'brain' в координаты (0,0) относительно RenderTexture, применяя к нему глобальный оттенок красного (0xff0000) и масштаб 1. Вторым вызовом мы рисуем сам спрайт sprite в координаты (128,128). Поскольку спрайту ранее был задан оттенок через setTint(0xff0000), при этой отрисовке он будет наложен на уже имеющееся содержимое RenderTexture (зеленый фон и красное изображение в углу).
Почему это важно? Практический вывод
Ключевое наблюдение: когда вы передаете в rt.draw() объект спрайта, Phaser использует его текущее визуальное состояние, включая все примененные к нему трансформации и оттенки (tint). Если же передается строковый ключ текстуры, отрисовывается ее оригинальная версия, а оттенок задается параметром метода.
Это может привести к неочевидным результатам, если вы хотите использовать спрайт как шаблон для RenderTexture, но при этом он уже визуально изменен в самой сцене. Для динамического рендеринга часто безопаснее использовать строковые ключи текстур, чтобы избежать побочных эффектов.
Что попробовать дальше
RenderTexture — мощный инструмент для динамического создания текстур, но требует внимания к источнику отрисовки. Используйте строковые ключи для предсказуемости или управляйте оттенками объекта-источника осознанно. Поэкспериментируйте: что будет, если сначала нарисовать спрайт, а потом залить RenderTexture? Или если применить clear() перед отрисовкой?
