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

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

Версия 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('pic1', 'assets/pics/robot-ai.jpg');
        this.load.image('pic2', 'assets/pics/baal-ai.jpg');
    }

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

        const sprite = this.add.image(400, 300, 'pic2');

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

        const text = this.add.text(10, 10, 'Click to randomize wipe width\nfx.wipeWidth: 0.1');

        this.input.on('pointerdown', () => {

            fx.wipeWidth = Math.random();

            text.setText([
                'Click to randomize wipe width',
                'fx.wipeWidth: ' + fx.wipeWidth
            ]);

        });

        this.tweens.add({
            targets: fx,
            progress: 1,
            repeatDelay: 1000,
            hold: 1000,
            yoyo: true,
            repeat: -1,
            duration: 2500
        });
    }
}

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

let game = new Phaser.Game(config);

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

Класс сцены Example наследуется от Phaser.Scene. В методе preload() задается базовый URL для загрузки и загружаются два изображения, которые будут использоваться в эффекте перехода.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('pic1', 'assets/pics/robot-ai.jpg');
    this.load.image('pic2', 'assets/pics/baal-ai.jpg');
}

Создание графики и применение фильтра

В методе create() сначала добавляется фоновое изображение (pic1). Затем поверх него размещается спрайт с изображением pic2. Именно к этому спрайту и будет применен фильтр.

Ключевой момент — активация системы фильтров для спрайта с помощью метода enableFilters(). После этого через цепочку вызовов filters.internal.addWipe() создается сам фильтр Wipe. Первый аргумент — wipeWidth (ширина зоны перехода), следующие два — координаты центра эффекта.

create ()
{
    this.add.image(400, 300, 'pic1');
    const sprite = this.add.image(400, 300, 'pic2');
    const fx = sprite.enableFilters().filters.internal.addWipe(0.1, 0, 0);
}

Интерактивное управление шириной перехода

Для демонстрации гибкости фильтра добавляется обработчик клика мыши. По каждому клику свойству fx.wipeWidth присваивается случайное значение от 0 до 1. Это свойство определяет ширину области, в которой происходит смешивание двух изображений. При значении 0 переход резкий, при увеличении значения — более плавный и размытый.

this.input.on('pointerdown', () => {
    fx.wipeWidth = Math.random();
    text.setText([
        'Click to randomize wipe width',
        'fx.wipeWidth: ' + fx.wipeWidth
    ]);
});

Автоматическая анимация прогресса эффекта

Чтобы эффект перехода воспроизводился автоматически и циклически, используется система твинов Phaser. Твин анимирует свойство progress фильтра от текущего значения до 1 и обратно (yoyo: true). Свойство progress управляет тем, какая часть верхнего изображения «стёрта» (0 — не видно, 1 — полностью видно).

Параметры repeatDelay и hold создают паузы в анимации, делая её более выразительной.

this.tweens.add({
    targets: fx,
    progress: 1,
    repeatDelay: 1000,
    hold: 1000,
    yoyo: true,
    repeat: -1,
    duration: 2500
});

Конфигурация игры и запуск

Стандартная конфигурация игры определяет её тип, размеры, цвет фона и корневой сценой делает наш класс Example.

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#0a0067',
    parent: 'phaser-example',
    scene: Example
};
let game = new Phaser.Game(config);

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

Фильтр Wipe — это простой, но мощный инструмент для создания анимированных переходов между визуальными слоями в Phaser. Комбинируя анимацию свойства progress и динамическое изменение wipeWidth, можно добиться разнообразных визуальных эффектов. Для экспериментов попробуйте: 1. Анимировать не progress, а координаты центра эффекта (`x,y`), чтобы создать переход, «вытекающий» из определенной точки экрана. 2. Связать изменение wipeWidth с движением курсора мыши для интерактивного управления резкостью перехода. 3. Применить фильтр к группе спрайтов или контейнеру для одновременного эффекта на нескольких элементах UI.