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

Визуальные эффекты — мощный инструмент для создания атмосферы и привлечения внимания игрока. В этой статье мы разберем, как легко добавить динамическое искажение к любому изображению или спрайту в Phaser 3, используя встроенный Displacement Filter. Этот метод позволяет оживить статичные фоны, создать эффекты магии, искажения пространства или просто добавить "живости" вашим сценам, управляя всего парой параметров. Мы начнем с базовой настройки и завершим анимированным эффектом.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('pic', 'assets/pics/taikodrummaster.jpg');
        this.load.image('distort', 'assets/textures/distortion4.png');
    }

    create ()
    {
        const pic = this.add.image(400, 300, 'pic');

        const fx = pic.enableFilters().filters.internal.addDisplacement('distort', -0.03, -0.03);

        this.tweens.add({
            targets: fx,
            x: 0.03,
            y: 0.03,
            yoyo: true,
            loop: -1,
            duration: 2000,
            ease: 'sine.inout'
        });
    }
}

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

const game = new Phaser.Game(config);

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

Как и в большинстве случаев в Phaser, работа начинается с методов жизненного цикла сцены. В preload мы загружаем два изображения: основную картинку, к которой будет применён эффект, и текстуру смещения (displacement map).

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('pic', 'assets/pics/taikodrummaster.jpg');
    this.load.image('distort', 'assets/textures/distortion4.png');
}

Важно: текстура искажения (в нашем случае 'distort') — это черно-белое изображение, где яркость пикселей определяет силу смещения. Phaser использует его как карту для сдвига пикселей исходного изображения.

Создание изображения и добавление фильтра

В методе create мы создаем основное изображение и сразу применяем к нему фильтр смещения. Ключевой момент — цепочка вызовов для активации фильтров.

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

const fx = pic.enableFilters().filters.internal.addDisplacement('distort', -0.03, -0.03);

Разберем по шагам: 1. pic.enableFilters() — включает систему фильтров для этого конкретного игрового объекта (pic). Этот метод необходимо вызвать перед добавлением любого фильтра. 2. .filters.internal — это доступ к внутреннему менеджеру фильтров объекта. 3. .addDisplacement('distort', -0.03, -0.03) — создает и добавляет фильтр смещения. Он принимает ключ текстуры и два начальных значения смещения по осям X и Y. Отрицательные значения (-0.03) означают начальное смещение влево и вверх.

Анимация параметров фильтра

Фильтр становится по-настоящему интересным, когда его параметры изменяются со временем. Phaser предоставляет для этого мощную систему твинов. Мы будем анимировать свойства `xиy` самого объекта фильтра, которые отвечают за силу смещения.

this.tweens.add({
    targets: fx,
    x: 0.03,
    y: 0.03,
    yoyo: true,
    loop: -1,
    duration: 2000,
    ease: 'sine.inout'
});

Параметры твина: - targets: fx — цель анимации — наш объект фильтра смещения. - x: 0.03, y: 0.03 — целевые значения. Фильтр плавно изменит смещение от (-0.03, -0.03) до (0.03, 0.03). - yoyo: true — после достижения цели, анимация проиграется в обратном порядке. - loop: -1 — бесконечное повторение цикла анимации. - duration: 2000 — длительность одного направления анимации (2 секунды). - ease: 'sine.inout' — плавная синусоидальная функция easing для более естественного движения.

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

Завершающий шаг — стандартная конфигурация объекта Phaser.Game. В этом примере важно убедиться, что размеры холста (width, height) соответствуют позиционированию изображения, чтобы оно оказалось по центру.

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

const game = new Phaser.Game(config);

Указав backgroundColor, мы создаем черный фон вокруг изображения, что может улучшить восприятие эффекта, если картинка не на весь экран.

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

Всего в несколько строк кода мы создали живой, притягивающий взгляд эффект искажения. Displacement Filter в Phaser — это прямой путь к визуально сложным результатам с минимальными усилиями. Для экспериментов попробуйте: использовать другие текстуры смещения (например, с более резкими градиентами или шумом Перлина), применить фильтр к анимированным спрайтам или UI-элементам, комбинировать его с другими фильтрами (например, с addGlow), или управлять параметрами `x`/`y` в реальном времени в ответ на действия игрока (например, при ударе).