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

Визуальные эффекты — это сердце игровой атмосферы. В этом примере мы покажем, как использовать объект `RenderTexture` для создания динамического следа из «искр», который следует за курсором или персонажем. Этот подход эффективнее, чем создание сотен отдельных спрайтов, так как мы рисуем кадры в одну текстуру, что снижает нагрузку на рендеринг. Вы научитесь управлять прозрачностью, цветом и геометрией отрисовки в реальном времени.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    player;
    rnd;
    rt;

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('dude', 'assets/sprites/phaser-dude.png');
    }

    create ()
    {
        this.rt = this.make.renderTexture({ x: 0, y: 0, width: 800, height: 600 });

        this.player = this.add.sprite(256, 256, 'dude').setOrigin(0.5, 0.5);

        this.rnd = Math.random;
    }

    update ()
    {
        this.player.setPosition(this.input.x, this.input.y);

        this.draw();
    }

    draw ()
    {
        this.rt.clear().render();

        this.rt.alpha = this.rnd();
        this.rt.tint = (0xFFFFFF << this.rnd() * 8092);

        for (let i = 0; i < 5; i++)
        {
            const rot = Math.floor((this.rnd() * Math.PI * 2) + 1);
            const dist = 75 + Math.floor((this.rnd() * 50) + 1);
            const x = this.player.x + dist * Math.cos(rot);
            const y = this.player.y + dist * Math.sin(rot);

            this.rt.draw('dude', x, y).render();
        }
    }
}

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

const game = new Phaser.Game(config);

Подготовка сцены и создание Render Texture

В методе preload загружается спрайт для эффекта. Ключевой объект создается в create. RenderTexture — это специальный игровой объект, который действует как динамический холст. Мы можем рисовать на нем другие игровые объекты или текстуры, а затем отображать его как единое целое.

this.rt = this.make.renderTexture({ x: 0, y: 0, width: 800, height: 600 });
this.player = this.add.sprite(256, 256, 'dude').setOrigin(0.5, 0.5);

Здесь this.make.renderTexture создает текстуру размером с игровое окно (800x600). Спрайт player изначально позиционируется в центре и будет следовать за курсором. setOrigin(0.5, 0.5) центрирует точку вращения и отрисовки спрайта.

Основной цикл и позиционирование

В методе update каждый кадр мы обновляем позицию спрайта player, привязывая ее к координатам курсора мыши или касания.

this.player.setPosition(this.input.x, this.input.y);
this.draw();

this.input.x и this.input.y предоставляют текущие координаты указателя. После обновления позиции вызывается пользовательский метод draw, который отвечает за визуализацию эффекта искр.

Рисование динамического эффекта искр

Метод draw — это ядро эффекта. Каждый вызов начинается с очистки текстуры от предыдущего кадра.

this.rt.clear().render();

Метод clear() стирает все, что было нарисовано на RenderTexture, а render() применяет это изменение. Далее задаются случайные значения прозрачности и цвета для всей текстуры, что создает мерцающий эффект.

this.rt.alpha = this.rnd();
this.rt.tint = (0xFFFFFF << this.rnd() * 8092);

this.rt.alpha устанавливает общую прозрачность (от 0 до 1). this.rt.tint применяет цветовой оттенок. Сдвиг битов << и умножение на случайное число генерируют широкий спектр цветов из белого базового цвета 0xFFFFFF.

Генерация частиц по окружности

Затем в цикле создаются пять «искр». Их позиции рассчитываются случайным образом на окружности вокруг спрайта player.

for (let i = 0; i < 5; i++) {
    const rot = Math.floor((this.rnd() * Math.PI * 2) + 1);
    const dist = 75 + Math.floor((this.rnd() * 50) + 1);
    const x = this.player.x + dist * Math.cos(rot);
    const y = this.player.y + dist * Math.sin(rot);
    this.rt.draw('dude', x, y).render();
}

Переменная rot — это случайный угол в радианах (от 0 до 2π). dist — случайное расстояние от центра в диапазоне от 75 до 125 пикселей. Используя тригонометрические функции Math.cos и Math.sin, вычисляются конечные координаты `xиy. Методthis.rt.drawрисует текстуру 'dude' в этих координатах наRenderTexture, аrender()` немедленно применяет отрисовку.

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

Использование RenderTexture для создания частичных эффектов — это мощная и производительная техника. Она позволяет создавать сложную динамическую графику без необходимости управлять множеством отдельных игровых объектов. Для экспериментов попробуйте изменить количество частиц в цикле, формулу распределения, добавьте масштабирование или вращение для каждой «искры», используя дополнительные параметры метода draw. Также можно накапливать след, убрав вызов clear(), или применить к текстуре шейдер для дополнительных визуальных искажений.