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

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

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    bg;
    gradient;

    create ()
    {
        // Sneaky background gradient
        this.bg = this.add.gradient({
            repeatMode: 2,
            shapeMode: 1,
            shape: { x: 0, y: 0.3 },
            bands: [
                {
                    colorStart: 0xbb9966,
                    colorEnd: 0x996666,
                    colorSpace: 1,
                    interpolation: 2,
                }
            ]
        }, 400, 300, 1400, 800)
        .setRotation(-0.25);

        this.gradient = this.add.gradient({
            shapeMode: 4, // CONIC_ASYMMETRIC
            bands: { colorStart: 0xffffff, colorEnd: 0x000000 },
            start: { x: 0.5, y: 0.5 }, // Start at middle
            shape: { x: 0.5, y: 0 } // Transition towards edge
        }, 400, 300, 400, 400);
    }

    update (time, delta)
    {
        const t = this.game.loop.time;
        this.bg.rotation = 0.25 * Math.sin(t / 3000);
        this.gradient.rotation = 0.03 * Math.sin(t / 1234);
        this.gradient.setPosition(
            400 + 16 * Math.sin(t / 876),
            300 + 16 * Math.sin(t / 765)
        );
    }
}

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

const game = new Phaser.Game(config);

Настройка сцены и базовый градиент фона

В классе сцены объявляются две переменные для хранения объектов градиентов: bg для фона и gradient для основного, динамического элемента.

В методе create() первым делом создаётся фоновый градиент. Он использует параметр shapeMode: 1, что соответствует линейному градиенту. Ключевой параметр repeatMode: 2 (GRADIENT_REPEAT) заставляет градиент тиражироваться, создавая полосатый узор.

this.bg = this.add.gradient({
    repeatMode: 2,
    shapeMode: 1,
    shape: { x: 0, y: 0.3 },
    bands: [
        {
            colorStart: 0xbb9966,
            colorEnd: 0x996666,
            colorSpace: 1,
            interpolation: 2,
        }
    ]
}, 400, 300, 1400, 800)
.setRotation(-0.25);

Обратите внимание: координаты (`x,y) и размеры (width,height`) передаются как аргументы после объекта конфигурации. Здесь градиент создаётся размером 1400x800, что больше области видимости камеры, и поворачивается на -0.25 радиана, чтобы полосы шли под углом.

Создание асимметричного конического градиента

Второй, главный градиент, создаётся в асимметричном коническом режиме. Это задаётся параметром shapeMode: 4 (CONIC_ASYMMETRIC). В отличие от симметричного конического градиента, асимметричный позволяет задать отдельно точку начала градиента (start) и точку, определяющую его форму (shape).

this.gradient = this.add.gradient({
    shapeMode: 4, // CONIC_ASYMMETRIC
    bands: { colorStart: 0xffffff, colorEnd: 0x000000 },
    start: { x: 0.5, y: 0.5 }, // Start at middle
    shape: { x: 0.5, y: 0 } // Transition towards edge
}, 400, 300, 400, 400);

Параметр bands определяет цветовые полосы. Здесь задана одна полоса от белого (0xffffff) к чёрному (0x000000). Координаты start и shape задаются в нормализованных значениях (от 0 до 1) относительно размеров объекта градиента. Установка start в центр (0.5, 0.5) означает, что градиент начинается из середины объекта. Параметр shape со значением { x: 0.5, y: 0 } указывает направление, в котором цвет меняется от colorStart к colorEnd — в данном случае вертикально вверх от центра.

Анимация градиентов в реальном времени

Динамика — это то, что оживляет статичные объекты. В методе update() мы анимируем оба градиента, используя текущее игровое время, доступное через this.game.loop.time.

Фоновый градиент плавно вращается вокруг своей оси, создавая эффект медленного движения облаков или песка.

const t = this.game.loop.time;
this.bg.rotation = 0.25 * Math.sin(t / 3000);

Основной конический градиент одновременно вращается и перемещается по эллиптической траектории, что создаёт сложное и привлекательное движение, похожее на орбиту или магическое свечение.

this.gradient.rotation = 0.03 * Math.sin(t / 1234);
this.gradient.setPosition(
    400 + 16 * Math.sin(t / 876),
    300 + 16 * Math.sin(t / 765)
);

Разные делители для времени (3000, 1234, 876, 765) гарантируют, что анимации вращения и движения не синхронизированы, что делает движение более естественным и менее механическим. Метод setPosition() перемещает центр градиента.

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

Для запуска примера необходима стандартная конфигурация игры Phaser. Ключевой параметр type: Phaser.WEBGL обязателен, так как объект Gradient требует WebGL-рендерера.

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

const game = new Phaser.Game(config);

Тёмный цвет фона (#2d2d2d) контрастирует с градиентами, делая их более выразительными. Убедитесь, что в HTML-документе есть элемент с id="phaser-example", куда будет встроена игра.

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

Асимметричный конический градиент в Phaser 3 — это гибкий инструмент для создания сложных визуальных эффектов с минимальным кодом. Экспериментируйте: попробуйте добавить больше цветовых полос в параметр bands, измените режим colorSpace и interpolation для другого восприятия цвета, анимируйте параметры start и shape для создания эффектов "схождения" или "расхождения" лучей. Такие градиенты отлично подойдут для создания аур вокруг персонажей, энергетических щитов, анимированных меню или психоделических фонов.