О чем этот пример

Иногда статичного отображения тайловой карты недостаточно. Например, для создания мини-карты, сложных эффектов или оптимизации отрисовки. Render Texture — это мощный инструмент Phaser, позволяющий рисовать на текстуре как на холсте. В этой статье мы рассмотрим, как отрисовать невидимый слой Tilemap на Render Texture и анимировать его камеру, чтобы создать эффект вращающейся карты. Это полезно для создания динамичных бэкграундов или изолированных областей рендеринга.

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class Example extends Phaser.Scene
{
    layer;
    rt;

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('tiles', 'assets/tilemaps/tiles/tmw_desert_spacing.png');
        this.load.tilemapTiledJSON('map', 'assets/tilemaps/maps/desert.json');
    }

    create ()
    {
        const map = this.make.tilemap({ key: 'map' });

        const tiles = map.addTilesetImage('Desert', 'tiles');

        this.layer = map.createLayer('Ground', tiles, 0, 0).setVisible(false);

        this.rt = this.add.renderTexture(400, 300, 800, 600);
    }

    update ()
    {
        this.rt.camera.rotation -= 0.01;

        this.rt.clear();

        this.rt.draw(this.layer);

        this.rt.render();
    }
}

const config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    scene: Example
};

const game = new Phaser.Game(config);

Загрузка ресурсов и создание скрытого слоя

В методе preload загружаются стандартные ресурсы для Tilemap: изображение с тайлами и JSON-файл карты, созданный в Tiled.

В create мы создаем саму карту. Ключевой момент — мы не отображаем слой Ground на основном экране. Вместо этого, вызвав метод .setVisible(false), мы делаем его невидимым. Однако объект слоя остается в памяти и полностью функционален, что позволяет использовать его как источник для рисования.

this.layer = map.createLayer('Ground', tiles, 0, 0).setVisible(false);

Затем создается объект Render Texture с центром в точке (400, 300) и размерами 800x600 пикселей. Эта текстура будет нашим виртуальным холстом.

this.rt = this.add.renderTexture(400, 300, 800, 600);

Принцип работы Render Texture

Render Texture (RT) — это специальный игровой объект, который содержит в себе буфер для рисования и собственную камеру. Вы можете отрисовывать на него другие игровые объекты, включая спрайты, группы, частицы и, как в нашем случае, слои тайловых карт.

Камера RT ведет себя так же, как и основная камера сцены: ее можно двигать, масштабировать и вращать. Любые трансформации камеры влияют на то, как объекты будут нарисованы на текстуре. Это открывает возможности для создания сложных видов, не затрагивая основное игровое пространство.

Анимация и цикл отрисовки в update

Вся магия происходит в методе update, который вызывается каждый кадр. Здесь реализуется цикл рендеринга на текстуру.

1. **Вращение камеры:** Сначала мы немного поворачиваем камеру Render Texture.

this.rt.camera.rotation -= 0.01;

2. **Очистка холста:** Чтобы предыдущий кадр не накладывался на новый, текстуру необходимо очистить.

this.rt.clear();

3. **Рисование слоя:** На очищенную текстуру рисуется наш невидимый слой тайлов this.layer. Координаты отрисовки учитывают текущее состояние камеры RT (ее поворот).

this.rt.draw(this.layer);

4. **Финальный рендеринг:** Метод .render() финализирует процесс. Важно отметить, что в большинстве простых случаев Phaser вызывает рендеринг автоматически, но при работе с clear() и draw() в цикле, явный вызов render() гарантирует корректное отображение.

this.rt.render();

В результате на экране мы видим не исходный слой карты, а его "снимок", сделанный на вращающуюся текстуру.

Что попробовать дальше

Использование Render Texture для отрисовки Tilemap — это эффективный прием для отделения логики отображения от основного игрового мира. Вы можете применять его для создания карт-радаров, статичных или анимированных фонов, оптимизации (если один сложный объект рисуется на текстуре один раз, а затем текстура выводится много раз) и множества визуальных эффектов. Попробуйте поэкспериментировать: измените rotation на zoom, двигайте камеру с помощью scrollX и scrollY, рисуйте на одну текстуру не только тайлы, но и спрайты игрока, или используйте несколько Render Texture для многослойных композиций.