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

Градиенты — это мощный инструмент для визуального оформления игр, позволяющий создавать атмосферные фоны, сияющие эффекты и живые UI-элементы без использования тяжелых текстур. Phaser 3 предоставляет гибкий API для работы с градиентами прямо в Canvas и WebGL контексте. В этой статье мы разберем практический пример создания двух типов градиентов: классического линейного для фона и билинейного для динамического объекта. Вы узнаете, как настраивать параметры цвета, анимации и как эффективно использовать их в своих проектах.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    bg;
    gradient;

    create ()
    {
        // Sneaky background gradient
        this.bg = this.add.gradient({
            shapeMode: 0,
            direction: Math.PI / 2,
            bands: [
                {
                    colorStart: 0x6699bb,
                    colorEnd: 0x000000,
                    colorSpace: 1,
                    interpolation: 4,
                }
            ]
        }, 400, 300, 1400, 800)
        .setRotation(-0.25);

        this.gradient = this.add.gradient({
            shapeMode: 1, // BILINEAR
            start: { x: 0.5, y: 0.5 }, // Start at middle
            shape: { x: 0.25, y: 0.25 } // Transition towards bottom right
        }, 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);

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

Класс Example расширяет Phaser.Scene. В методе create() мы создаем два градиента. Первый, this.bg, служит фоновым элементом.

Ключевые параметры, передаваемые в this.add.gradient(): - shapeMode: 0 — указывает на использование линейного градиента. - direction: Math.PI / 2 — задает направление градиента (в данном случае 90 градусов, сверху вниз). - bands — массив, определяющий цветовые полосы градиента. Здесь одна полоса, плавно переходящая от голубого (0x6699bb) к черному (0x000000). - colorSpace: 1 и interpolation: 4 — параметры, влияющие на цветовое пространство и алгоритм интерполяции, что дает более гладкий переход.

После создания градиент позиционируется, масштабируется и поворачивается с помощью метода .setRotation().

this.bg = this.add.gradient({
    shapeMode: 0,
    direction: Math.PI / 2,
    bands: [
        {
            colorStart: 0x6699bb,
            colorEnd: 0x000000,
            colorSpace: 1,
            interpolation: 4,
        }
    ]
}, 400, 300, 1400, 800)
.setRotation(-0.25);

Создание билинейного градиента для игрового объекта

Второй градиент, this.gradient, демонстрирует более сложный режим BILINEAR. Этот тип градиента создает цветовое поле, которое изменяется в двух направлениях от центральной точки.

Его конфигурация отличается:
- `shapeMode: 1` — активирует билинейный режим.
- `start: { x: 0.5, y: 0.5 }` — точка, от которой начинается градиент. Значения от 0 до 1 относительно размеров объекта. (0.5, 0.5) — это центр.
- `shape: { x: 0.25, y: 0.25 }` — определяет вектор, вдоль которого происходит изменение цвета. Здесь цвет меняется по направлению к точке с координатами (0.25, 0.25) от центра, т.е. в сторону нижнего правого угла.

Этот градиент создается с меньшими размерами (400x400) и позиционируется в центре экрана (400, 300).

this.gradient = this.add.gradient({
    shapeMode: 1, // BILINEAR
    start: { x: 0.5, y: 0.5 }, // Start at middle
    shape: { x: 0.25, y: 0.25 } // Transition towards bottom right
}, 400, 300, 400, 400);

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

Вся магия происходит в методе update(). Phaser автоматически вызывает этот метод каждый кадр, передавая общее время работы игры и время, прошедшее с предыдущего кадра.

Мы используем this.game.loop.time для получения текущего времени в миллисекундах. Это значение позволяет создавать плавные, зависящие от времени анимации.

1. **Вращение фона:** Угол вращения фонового градиента (`this.bg.rotation`) меняется по синусоидальному закону с большой амплитудой и периодом, создавая медленное, едва заметное движение.
2. **Вращение и движение объекта:** Билинейный градиент (`this.gradient`) также вращается, но с меньшей амплитудой. Более интересно его движение по экрану, задаваемое методом `setPosition()`. Координаты X и Y вычисляются независимо с помощью `Math.sin()`, но с разными периодами, что создает сложную траекторию в виде фигуры Лиссажу.
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)
    );
}

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

Код завершается созданием конфигурационного объекта и экземпляра игры Phaser.Game. Это стандартная настройка для любого проекта на Phaser 3.

- type: Phaser.WEBGL — используем WebGL рендерер для лучшей производительности и поддержки эффектов. - width и height — определяют размер игрового холста. - backgroundColor — цвет фона, который будет виден до отрисовки сцены или вокруг нее. - parent — ID HTML-элемента, в который будет встроен игровой холст. - scene — класс основной сцены, которая будет запущена сразу после инициализации игры.

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

const game = new Phaser.Game(config);

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

Градиенты в Phaser 3 — это не просто статичный фон, а полноценные игровые объекты, которые можно анимировать, трансформировать и использовать для создания сложных визуальных эффектов с минимальными затратами ресурсов. Экспериментируйте: попробуйте добавить больше полос в bands, измените colorSpace и interpolation для другого визуального восприятия, используйте билинейный градиент в качестве маски для спрайта или создайте пульсирующий UI-элемент, меняя его scale в update().