О чем этот пример
RenderTexture в Phaser 3 — это мощный инструмент для динамического рисования и компоновки графики во время выполнения игры. Он работает как внутренний холст, на который можно отрисовывать текстуры, спрайты или даже другие RenderTexture. Однако его размер не всегда фиксирован. В этой статье мы разберемся, как правильно использовать метод `resize()` для изменения размеров RenderTexture, и почему порядок вызова методов имеет ключевое значение для конечного результата. Это поможет вам избежать ошибок при создании динамических интерфейсов, мини-карт или эффектов постобработки.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Demo extends Phaser.Scene {
constructor() {
super({
key: 'examples'
})
}
preload() {
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('mushroom', 'assets/sprites/mushroom2.png');
}
create() {
var rt = this.add.renderTexture(400, 300, 64, 64);
rt
.resize(128, 128)
.drawFrame('mushroom', undefined, 0, 0)
.drawFrame('mushroom', undefined, 0, 64)
.drawFrame('mushroom', undefined, 64, 0)
.drawFrame('mushroom', undefined, 64, 64)
}
}
var config = {
type: Phaser.AUTO,
scale: {
parent: 'phaser-example',
width: 800,
height: 600,
},
scene: Demo
};
var game = new Phaser.Game(config);
Что такое RenderTexture?
RenderTexture (RT) — это особый игровой объект, который представляет собой динамически создаваемую текстуру. Её можно использовать как целевой буфер для отрисовки. Это похоже на создание снимка нескольких графических элементов и сохранение его в виде единого изображения, которое затем можно использовать как обычный спрайт.
Основные преимущества: * **Производительность:** Отрисовав сложную композицию один раз в RT, вы рендерите её в каждом кадре как единый объект, а не как множество отдельных. * **Динамика:** Содержимое RT можно менять во время выполнения игры. * **Гибкость:** RT можно масштабировать, вращать, применять к нему фильтры, как к любому другому игровому объекту.
Создается он просто:
Как работает метод resize()?
Метод resize(width, height) изменяет внутренние размеры текстуры RenderTexture. Важно понимать, что это действие очищает текущее содержимое RenderTexture. После вызова resize() холст становится пустым, и вам нужно заново нарисовать на нём всё необходимое.
В исходном примере показана типичная ошибка и её решение. Если метод resize() вызывается после команд рисования, то всё нарисованное будет потеряно. Правильный подход — сначала изменить размер, а затем наполнить текстуру содержимым.
Посмотрите на цепочку вызовов в примере:
Разбор примера: порядок имеет значение
Давайте подробно разберем каждую строчку из метода create() в исходном коде.
var rt = this.add.renderTexture(400, 300, 64, 64);
Здесь создается RenderTexture с начальными координатами (400, 300) и начальным размером 64x64 пикселя.
rt.resize(128, 128)
Это ключевой момент. Мы **сразу** изменяем размер текстуры до 128x128. Этот вызов очистил бы предыдущее содержимое, если бы оно было.
.drawFrame('mushroom', undefined, 0, 0)
.drawFrame('mushroom', undefined, 0, 64)
.drawFrame('mushroom', undefined, 64, 0)
.drawFrame('mushroom', undefined, 64, 64)
Теперь, на очищенный и увеличенный холст, мы рисуем четыре гриба (фреймы текстуры 'mushroom'). Метод drawFrame() принимает ключ текстуры, имя фрейма (или undefined для основного фрейма) и координаты X, Y для отрисовки **внутри** RenderTexture. Благодаря тому, что мы сначала выполнили resize(), все четыре гриба помещаются на новый холст размером 128x128, создавая композицию 2x2.
Если бы цепочка выглядела как rt.drawFrame(...).resize(128,128), то сначала на холст 64x64 были бы нарисованы грибы (часть из них оказалась бы за границами и не была бы видна), а затем операция resize() стерла бы этот результат, и мы увидели бы только пустую текстуру.
Практическое применение и паттерны
Использование resize() особенно полезно в следующих сценариях:
1. **Адаптивные элементы интерфейса:** Вы можете создать RT для панели навыков и изменять её размер в зависимости от количества разблокированных умений.
2. **Динамические мини-карты:** Размер карты может меняться при увеличении уровня, и resize() позволяет подогнать под неё RenderTexture.
3. **Оптимизация:** Если вы понимаете, что RT стал слишком большим для своего текущего содержимого, вы можете уменьшить его для экономии видеопамяти.
Основной паттерн работы всегда одинаков:
1. Создать или получить ссылку на RenderTexture.
2. Вызвать resize() с новыми размерами.
3. Последовательно вызвать методы рисования (draw, drawFrame, drawSlice и т.д.), чтобы заполнить текстуру.
Пример паттерна для динамического обновления:
Что попробовать дальше
Метод resize() — это простой, но мощный инструмент для управления размером RenderTexture в Phaser 3. Главное правило: всегда изменяйте размер до начала рисования, так как эта операция сбрасывает содержимое текстуры. Используйте этот подход для создания гибких и динамических графических композиций прямо во время выполнения вашей игры.
**Идеи для экспериментов:** Попробуйте анимировать изменение размера RT в ответ на игровые события (например, при подборе бонуса). Или создайте сложную композицию из множества спрайтов в RT, а затем примените к самой RT эффекты размытия или свечения через постобработку. Исследуйте, как изменение размера RT влияет на производительность в мобильных браузерах.
