О чем этот пример
Работа с объектами, превышающими размер экрана — классическая задача при разработке игр с прокруткой уровней. Встроенная `RenderTexture` в Phaser 3 позволяет эффективно создавать и отрисовывать большие составные изображения, которые можно плавно исследовать с помощью камеры. Этот подход идеально подходит для генерации тайловых карт, фоновых текстур или целых уровней в памяти перед их отображением, что снижает нагрузку на рендеринг в реальном времени. В статье мы разберем пример, где создается текстура размером 1400x1200 пикселей, в четыре раза превышающая область видимости камеры (800x600). Вы научитесь заполнять ее цветом, рисовать на ней множественные спрайты и реализуете плавное управление камерой с клавиатуры для навигации по этому большому холсту.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
controls;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('ayu', 'assets/pics/ayu.png');
}
create ()
{
const rt = this.add.renderTexture(700, 600, 1400, 1200);
rt.fill(0x2d2d2d);
for (let y = 0; y < 4; y++)
{
for (let x = 0; x < 4; x++)
{
rt.draw('ayu', x * 404, y * 371);
}
}
rt.render();
const cursors = this.input.keyboard.createCursorKeys();
const controlConfig = {
camera: this.cameras.main,
left: cursors.left,
right: cursors.right,
up: cursors.up,
down: cursors.down,
acceleration: 0.06,
drag: 0.0005,
maxSpeed: 1.0
};
this.controls = new Phaser.Cameras.Controls.SmoothedKeyControl(controlConfig);
this.add.text(10, 10, 'Cursors to move', { font: '16px Courier', fill: '#ffffff' }).setScrollFactor(0);
}
update (time, delta)
{
this.controls.update(delta);
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#2d2d88',
scene: Example
};
const game = new Phaser.Game(config);
Создание и базовая настройка RenderTexture
Ключевой объект в этом примере — RenderTexture. Это особый тип игрового объекта (Game Object), который действует как динамический холст в памяти. Мы можем рисовать на нем другие текстуры, а затем отобразить результат как единое изображение.
В методе create() создается экземпляр RenderTexture. Его начальные координаты (700, 600) помещают центр текстуры в центр экрана. Размеры (1400, 1200) задают холст, который будет больше области обзора камеры.
const rt = this.add.renderTexture(700, 600, 1400, 1200);
Сразу после создания мы заливаем всю текстуру однотонным цветом, используя метод fill(). Это создает темно-серый фон для нашей композиции.
rt.fill(0x2d2d2d);
Пакетное рисование спрайтов на текстуре
Основное преимущество RenderTexture — возможность отрисовать множество спрайтов или примитивов за один проход, прежде чем выводить их на экран. Это выполняется методом draw().
В примере используется двойной цикл for, который рисует текстуру 'ayu' 16 раз (4x4), располагая каждый экземпляр со смещением. Координаты для каждого рисунка рассчитываются путем умножения индексов циклов на размеры изображения (примерно 404x371). Таким образом создается сетка из картинок.
for (let y = 0; y < 4; y++)
{
for (let x = 0; x < 4; x++)
{
rt.draw('ayu', x * 404, y * 371);
}
}
После того как все элементы отрисованы на внутреннем буфере RenderTexture, необходимо вызвать метод render(). Этот метод финализирует процесс и делает текстуру готовой к отображению игровым движком.
rt.render();
Настройка плавного управления камерой
Поскольку RenderTexture является дочерним объектом сцены, на него распространяются трансформации камеры. Чтобы исследовать части текстуры, скрытые за границами экрана, нужно двигать камеру.
В примере для этого используется Phaser.Cameras.Controls.SmoothedKeyControl — встроенный контроллер, который обеспечивает плавное, инерционное движение камеры при нажатии клавиш. Сначала создается объект конфигурации, который связывает контроллер с главной камерой (this.cameras.main) и клавиша-стрелками.
const controlConfig = {
camera: this.cameras.main,
left: cursors.left,
right: cursors.right,
up: cursors.up,
down: cursors.down,
acceleration: 0.06,
drag: 0.0005,
maxSpeed: 1.0
};
Параметры acceleration, drag и maxSpeed тонко настраивают поведение движения, делая его более естественным.
Контроллер создается на основе этой конфигурации, а в методе update() каждый кадр вызывается его метод update(delta), чтобы обработать ввод и переместить камеру.
this.controls = new Phaser.Cameras.Controls.SmoothedKeyControl(controlConfig);
update (time, delta)
{
this.controls.update(delta);
}
Для удобства на экран добавляется неподвижный текст (.setScrollFactor(0)), который всегда виден и поясняет управление.
Конфигурация игры и роль камеры
Важно понимать соотношение размеров. В конфигурации игры (config) установлено разрешение 800x600 пикселей. Это размер области отрисовки и, по умолчанию, размер видимой области главной камеры.
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#2d2d88',
scene: Example
};
RenderTexture создается размером 1400x1200. Это означает, что камера (800x600) может показывать только часть этой большой текстуры за один раз. Управление камерой позволяет сдвигать этот "оконный вид" по всей площади текстуры, создавая эффект прокрутки большого уровня или карты.
Фоновый цвет игры (#2d2d88) отличается от цвета заливки текстуры (0x2d2d2d), поэтому при движении камеры за пределы текстуры будет виден синий фон игры.
Что попробовать дальше
RenderTexture — это мощный инструмент для подготовки сложных, составных изображений прямо во время выполнения игры. Он особенно полезен для динамической генерации уровней, крупных фонов или интерфейсов. Вы можете экспериментировать: попробуйте рисовать на текстуре не только изображения, но и геометрические фигуры, добавлять различные эффекты смешивания (blendMode) или создать несколько слоев RenderTexture для parallax-прокрутки. Также интересно будет привязать движение камеры не к клавиатуре, а к положению игрового персонажа, создав классическую камеру следования.
