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

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

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

Живой запуск

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

Исходный код


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

        this.rope;
        this.count = 0;
    }

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

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

        this.rope = this.add.rope(400, 300, 'snake', null, 64);

        //  You can set the alpha of a Rope just like any other Game Object
        //  You can also set the alpha for each vertice in the Rope.
        //  If you do that, this alpha value is multiplied with the vertice alpha.

        this.tweens.add({
            targets: this.rope,
            alpha: 0.1,
            ease: 'sine.inout',
            duration: 2000,
            yoyo: true,
            repeat: -1
        });
    }

    update ()
    {
        this.count += 0.1;

        let points = this.rope.points;

        for (let i = 0; i < points.length; i++)
        {
            points[i].y = Math.sin(i * 0.15 + this.count) * 24;
        }

        this.rope.setDirty();
    }
}

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

let game = new Phaser.Game(config);

Инициализация сцены и загрузка ресурсов

В конструкторе класса сцены мы подготавливаем свойства для хранения основного объекта и счётчика анимации.

В методе preload загружаются два изображения: фон (bg) и текстура, которая будет "натянута" на верёвку (snake). Обратите внимание на использование setBaseURL — это удобно, если все ресурсы хранятся в одном месте.

this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/rope/underwater.jpg');
this.load.image('snake', 'assets/rope/snake.png');

Создание верёвки и анимация альфа-канала

В методе create сначала добавляется фоновое изображение. Затем создаётся сам объект Rope с помощью фабричного метода this.add.rope. Параметры: X и Y координаты начала, ключ текстуры, массив точек (здесь null, что создаст горизонтальную верёвку) и количество сегментов (64).

this.rope = this.add.rope(400, 300, 'snake', null, 64);

Сразу после создания к верёвке применяется твин (tween). Он циклично меняет свойство alpha объекта от начального значения (1) до 0.1 и обратно, создавая эффект пульсации прозрачности. yoyo: true и repeat: -1 обеспечивают бесконечное повторение.

this.tweens.add({
    targets: this.rope,
    alpha: 0.1,
    ease: 'sine.inout',
    duration: 2000,
    yoyo: true,
    repeat: -1
});

Динамическое обновление формы в update

Это сердце анимации формы. Каждый кадр увеличивается счётчик this.count, что обеспечивает непрерывное движение. Мы получаем массив точек points, из которых состоит верёвка.

В цикле для Y-координаты каждой точки вычисляется синусоидальное значение. Множитель i * 0.15 обеспечивает сдвиг фазы для каждой последующей точки, создавая волну. Амплитуда волны — 24 пикселя. this.count заставляет эту волну "плыть" вдоль верёвки.

this.count += 0.1;
let points = this.rope.points;
for (let i = 0; i < points.length; i++) {
    points[i].y = Math.sin(i * 0.15 + this.count) * 24;
}

После изменения координат точек необходимо вручную вызвать метод this.rope.setDirty(). Это критически важный шаг, который сообщает системе рендеринга, что геометрия объекта изменилась и её нужно перерисовать.

this.rope.setDirty();

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

Объект Rope в Phaser 3 — мощный инструмент для создания сложных деформаций и плавных анимаций на основе текстур. Комбинируя анимацию вершин (точек) и свойств самого объекта (вроде alpha), можно добиться впечатляющих визуальных эффектов с минимальным кодом. Для экспериментов попробуйте: изменить форму волны на косинус или более сложную математическую функцию; анимировать свойство alpha не для всего объекта, а для отдельных точек через points[i].alpha; использовать текстуру с прозрачностью (PNG) вместе с анимацией альфа-канала для многослойных эффектов.