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

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

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

Живой запуск

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

Исходный код


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

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('bg', 'assets/pics/spacey.jpg');
    }

    create ()
    {
        this.add.image(400, 300, 'bg');

        let line = 0;

        const message = [
            'Welcome to',
            'Phaser 4 Wipe',
            'Using Text Filter',
            'and a Tween'
        ];

        const text = this.add.text(400, 300, message[line], { fontFamily: 'Arial Black', fontSize: 80 });

        const gradient = text.context.createLinearGradient(0, 0, 0, text.height);

        gradient.addColorStop(0, '#f26522');
        gradient.addColorStop(0.5, '#fff200');
        gradient.addColorStop(0.5, '#f7941d');
        gradient.addColorStop(1, '#ed1c24');

        text.setFill(gradient);
        text.setOrigin(0.5, 0.5);

        const fx = text.enableFilters().filters.internal.addWipe(0.1, 0, 0, 1);

        this.tweens.add({
            targets: fx,
            progress: 1,
            hold: 500,
            duration: 3000,
            repeat: -1,
            onRepeat: () => {

                line++;

                if (line === message.length)
                {
                    line = 0;
                }

                text.setText(message[line]);

                fx.progress = 0;

            }
        });
    }
}

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

let game = new Phaser.Game(config);

Подготовка сцены и загрузка ресурсов

Код начинается с создания стандартной сцены Phaser. В методе preload задается базовый URL для загрузки и загружается одно фоновое изображение. Это изображение будет служить статичным задним фоном для нашего анимированного текста.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('bg', 'assets/pics/spacey.jpg');
}

Создание текстового объекта и настройка градиента

В методе create сначала добавляется фоновое изображение. Затем создается массив строк message и объект текста text. Ключевой момент — использование Canvas API через свойство text.context для создания линейного градиента. Градиент настраивается с несколькими цветовыми остановками, создавая эффект плавного перехода от оранжевого к желтому и красному. Этот градиент применяется к тексту с помощью метода setFill. Метод setOrigin центрирует текст относительно его координат.

const text = this.add.text(400, 300, message[line], { fontFamily: 'Arial Black', fontSize: 80 });

const gradient = text.context.createLinearGradient(0, 0, 0, text.height);
gradient.addColorStop(0, '#f26522');
gradient.addColorStop(0.5, '#fff200');
gradient.addColorStop(0.5, '#f7941d');
gradient.addColorStop(1, '#ed1c24');

text.setFill(gradient);
text.setOrigin(0.5, 0.5);

Активация фильтров и добавление Wipe

Чтобы применить к тексту визуальные эффекты, его нужно перевести в режим фильтров. Цепочка вызовов text.enableFilters().filters.internal.addWipe() делает именно это. Метод enableFilters() активирует систему фильтров для объекта, а filters.internal.addWipe() добавляет конкретный фильтр типа «Wipe» (проявление). Первый аргумент (0.1) задает начальное значение прогресса эффекта (текст почти не виден), остальные аргументы определяют направление проявления. Возвращаемый объект fx — это и есть сам фильтр, свойством которого мы будем управлять.

const fx = text.enableFilters().filters.internal.addWipe(0.1, 0, 0, 1);

Анимация с помощью Tween и циклическая смена текста

Сердце анимации — твин Phaser, который плавно меняет свойство progress фильтра от начального значения до 1 (полное проявление текста). В конфигурации твина важны параметры hold (пауза после завершения анимации) и repeat: -1 (бесконечное повторение). Колбэк onRepeat срабатывает при каждом новом цикле анимации. Внутри него происходит смена строки в текстовом объекте и сброс прогресса фильтра обратно к начальному значению, что создает цикл: проявление новой строки -> пауза -> сброс -> проявление следующей строки.

this.tweens.add({
    targets: fx,
    progress: 1,
    hold: 500,
    duration: 3000,
    repeat: -1,
    onRepeat: () => {
        line++;
        if (line === message.length) { line = 0; }
        text.setText(message[line]);
        fx.progress = 0;
    }
});

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

Используя связку текстовых объектов, фильтров и твинов в Phaser, можно легко создавать сложные и привлекательные текстовые анимации прямо «из коробки», без необходимости подключать внешние библиотеки. Для экспериментов попробуйте изменить параметры градиента, поиграть с другими фильтрами из коллекции filters.internal (например, addGlow или addBarrel), заменить линейный wipe на другой тип перехода или привязать анимацию не к таймеру, а к игровому событию.