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

Динамические текстуры в Phaser — мощный инструмент для рендеринга графики в реальном времени прямо в игровом цикле. Этот пример демонстрирует, как с помощью метода `stamp` наносить спрайты на текстуру и как использовать `clear` для очистки её области. Такой подход полезен для создания эффектов рисования, динамических фонов или систем частиц, где требуется полный контроль над пикселями.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    constructor ()
    {
        super();

        this.r = 0;
    }

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('apple', 'assets/sprites/apple.png');
        this.load.glsl('bundle', 'assets/shaders/bundle.glsl.js');
    }

    create ()
    {
        const texture = this.textures.addDynamicTexture('shaderTexture', 512, 512);

        this.apples = [];

        for (let i = 0; i < 64; i++)
        {
            const x = Phaser.Math.Between(25, 487);
            const y = Phaser.Math.Between(25, 487);

            this.apples.push({ x, y });
        }

        this.texture = texture;

        this.add.shader('Tunnel', 400, 300, 800, 600, [ 'shaderTexture' ]);
    }

    update ()
    {
        this.texture.fill(0x000066);

        this.apples.forEach(apple => {

            this.texture.stamp('apple', null, apple.x, apple.y, { rotation: this.r });

        });

        this.texture.clear(0, 0, 100, 100);
        this.r += 0.1;
    }
}

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

const game = new Phaser.Game(config);

Создание динамической текстуры

В методе create создаётся динамическая текстура размером 512x512 пикселей. Она будет использоваться как буфер для рисования.

const texture = this.textures.addDynamicTexture('shaderTexture', 512, 512);

Затем подготавливается массив this.apples с координатами 64 случайных точек. Эти точки будут позициями для штамповки спрайтов яблока.

for (let i = 0; i < 64; i++) {
    const x = Phaser.Math.Between(25, 487);
    const y = Phaser.Math.Between(25, 487);
    this.apples.push({ x, y });
}

Текстура сохраняется в свойстве this.texture для использования в update. Также в сцену добавляется шейдер 'Tunnel', который использует нашу динамическую текстуру в качестве входного изображения.

Цикличное обновление текстуры

Каждый кадр в методе update текстура полностью заливается тёмно-синим цветом с помощью fill. Это очищает результаты предыдущего кадра.

this.texture.fill(0x000066);

Затем для каждой точки из массива this.apples на текстуру штампуется спрайт 'apple'. Метод stamp принимает ключ изображения, фрейм, координаты X и Y, а также объект опций — здесь это вращение rotation, которое увеличивается каждый кадр.

this.apples.forEach(apple => {
    this.texture.stamp('apple', null, apple.x, apple.y, { rotation: this.r });
});

После штамповки всех спрайтов вызывается clear, который очищает прямоугольную область размером 100x100 пикселей в левом верхнем углу текстуры.

this.texture.clear(0, 0, 100, 100);

В конце кадра угол вращения this.r увеличивается на 0.1 радиана, что приводит к плавному вращению всех яблок.

Практическое применение методов

Метод stamp позволяет эффективно рендерить множество спрайтов на одной текстуре, что может быть использовано для создания сложных составных изображений или спрайтовых анимаций.

this.texture.stamp(key, frame, x, y, options)

Метод clear полезен, когда нужно стереть часть текстуры, не перерисовывая её полностью. Например, для реализации ластика в рисовалке или для удаления объектов с динамической карты.

this.texture.clear(x, y, width, height)

Важно помнить, что clear задаёт прозрачный чёрный цвет (0x00000000) в указанной области, что может влиять на прозрачность в шейдере.

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

Динамические текстуры открывают возможности для procedural графики в Phaser. Экспериментируйте: попробуйте менять параметры clear для создания анимации исчезновения, используйте разные спрайты в stamp или комбинируйте текстуры с другими шейдерами для уникальных визуальных эффектов.