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

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

Версия 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('raster', 'assets/demoscene/raster-bw-64.png');
    }

    create ()
    {
        const group = this.add.group();

        group.createMultiple({ key: 'raster', repeat: 8 });

        let ci = 0;
        const colors = [ 0xef658c, 0xff9a52, 0xffdf00, 0x31ef8c, 0x21dfff, 0x31aade, 0x5275de, 0x9c55ad, 0xbd208c ];

        const _this = this;

        group.children.forEach(child =>
        {

            child.x = 100;
            child.y = 300;
            child.depth = 9 - ci;

            child.tint = colors[ci];

            ci++;

            _this.tweens.add({
                targets: child,
                x: 700,
                yoyo: true,
                repeat: -1,
                ease: 'Sine.easeInOut',
                duration: 1500,
                delay: 100 * ci
            });

        });
    }
}

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

const game = new Phaser.Game(config);

Загрузка ресурсов и настройка сцены

Вся работа начинается в методе preload. Здесь мы загружаем единственное изображение, которое будет использоваться для создания всех полос. Важно установить базовый URL для загрузчика, чтобы корректно подгрузить ассет из репозитория с примерами.

preload()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('raster', 'assets/demoscene/raster-bw-64.png');
}

После загрузки Phaser автоматически перейдёт к методу create, который является точкой инициализации игровой логики. Конфигурация игры задаётся в объекте config, где определяется тип рендерера, размеры холста и класс основной сцены.

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

const game = new Phaser.Game(config);

Создание группы и настройка спрайтов

В методе create первым делом создаётся группа (Group). Группы в Phaser — это мощный инструмент для управления коллекциями игровых объектов. С помощью метода createMultiple мы создаём несколько копий одного спрайта.

const group = this.add.group();
group.createMultiple({ key: 'raster', repeat: 8 });

Параметр repeat: 8 указывает, что нужно создать 8 дополнительных спрайтов (плюс один исходный), итого 9 объектов. Далее определяется палитра цветов в HEX-формате, которая будет применена к полосам.

Затем в цикле forEach настраивается каждый спрайт в группе. Ключевые моменты: - Позиция `xиy` задаётся одинаковой для всех, создавая начальное вертикальное выравнивание. - Свойство depth управляет порядком отрисовки (z-index). Значение 9 - ci гарантирует, что первая созданная полоса (с индексом 0) будет иметь глубину 9 и отрисуется поверх остальных, создавая иллюзию слоёв. : Свойству tint присваивается цвет из массива, эффективно окрашивая монохромный спрайт.

let ci = 0;
const colors = [ 0xef658c, 0xff9a52, 0xffdf00, 0x31ef8c, 0x21dfff, 0x31aade, 0x5275de, 0x9c55ad, 0xbd208c ];

group.children.forEach(child =>
{
    child.x = 100;
    child.y = 300;
    child.depth = 9 - ci;
    child.tint = colors[ci];
    ci++;
    // Твин будет добавлен здесь
});

Анимация с помощью системы твинов

Сердце эффекта — система твинов Phaser (Tweens). Для каждого спрайта в том же цикле создаётся анимация движения.

_this.tweens.add({
    targets: child,
    x: 700,
    yoyo: true,
    repeat: -1,
    ease: 'Sine.easeInOut',
    duration: 1500,
    delay: 100 * ci
});

Разберём параметры этого твина: - targets: объект, который будет анимирован (наш спрайт child). - x: 700: конечная координата по оси X. - yoyo: true: после достижения конечной точки анимация проиграется в обратном порядке. - repeat: -1: анимация повторяется бесконечно. - ease: 'Sine.easeInOut': функция плавности, которая обеспечивает мягкое ускорение и замедление. - duration: 1500: длительность одного цикла (вперед или назад) в миллисекундах. - delay: 100 * ci: задержка перед стартом анимации. Это ключевой параметр! Умножение на индекс ci создаёт эффект «волны», где каждая следующая полоса начинает движение чуть позже предыдущей.

Обратите внимание на использование _this = this. Это необходимо, потому что внутри callback-функции forEach контекст this был бы другим. Мы сохраняем ссылку на экземпляр сцены, чтобы иметь доступ к this.tweens.

Принцип работы итогового эффекта

В результате всех этих действий мы получаем синхронизированную анимацию. Девять вертикальных полос, окрашенных в разные цвета и расположенных в определённом порядке по глубине, начинают движение с задержкой. Они движутся от X=100 до X=700 и обратно по плавной синусоидальной траектории.

Из-за разницы в delay и одинаковой duration создаётся перспектива: полосы никогда не выстраиваются в одну линию, а постоянно образуют движущиеся узоры. Эффект глубины усиливается за счёт свойства depth — более «близкие» к зрителю полосы (с большим значением depth) перекрывают дальние.

Использование одного графического ассета (raster) с последующим окрашиванием через tint — это оптимизационный приём. Он позволяет создать разноцветную анимацию, загрузив лишь одну текстуру в видеопамять, что положительно сказывается на производительности.

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

Этот пример — отличная основа для экспериментов. Попробуйте изменить массив colors на свою палитру. Поиграйте с параметрами твина: замените ease на Cubic, Quad или Back для более резкого или «пружинящего» движения. Измените оси анимации: заставьте полосы двигаться по вертикали (`y) или по диагонали. Добавьте вращение (angle) или масштабирование (scale`) в твин для более сложных визуальных эффектов. Наконец, вы можете реагировать на клик мыши, перезапуская анимацию или динамически создавая новые полосы.