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

Визуальное оформление — ключевая часть игрового опыта. Phaser 3 предоставляет мощную систему градиентов, которая позволяет создавать сложные фоны и эффекты прямо в коде, без использования внешних изображений. В этой статье мы разберем пример использования конического симметричного градиента (`CONIC_SYMMETRIC`) для создания динамического, «живого» визуального элемента, который можно анимировать в реальном времени, экономя ресурсы и добавляя игре уникальный стиль.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    bg;
    gradient;

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

        this.gradient = this.add.gradient({
            shapeMode: 3, // CONIC_SYMMETRIC
            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);

Разбираем конфигурацию сцены

Основой любого примера Phaser является конфигурация игры и класс сцены. В данном случае мы используем WebGL-рендерер и задаем базовые параметры окна.

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. В нем объявлены два свойства: bg для фонового градиента и gradient для основного конического градиента. Жизненный цикл сцены управляется методами create() и update().

Создание фонового градиента в create()

Метод create() вызывается один раз при инициализации сцены. Здесь создаются два градиента. Первый, this.bg, служит фоном. Обратите внимание на его параметры.

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

* repeatMode: 3: Задает режим повторения градиента. * shapeMode: 1: Определяет форму градиента (линейный, радиальный и т.д.). * shape: Точка, к которой стремится градиент (в нормализованных координатах). * bands: Массив цветовых полос. Здесь одна полоса плавно переходит от зеленоватого к фиолетовому. * Метод this.add.gradient принимает конфиг, координаты центра (x, y), ширину и высоту. * .setRotation(-0.25) сразу применяет начальный поворот к объекту.

Сердце примера: конический симметричный градиент

Второй градиент — главный объект изучения. Для него используется shapeMode: 3, что соответствует константе Phaser.GameObjects.Gradient.CONIC_SYMMETRIC.

this.gradient = this.add.gradient({
    shapeMode: 3, // CONIC_SYMMETRIC
    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);
*   `shapeMode: 3` (CONIC_SYMMETRIC): Создает конический градиент, который симметрично расходится из центральной точки (`start`). Цвет меняется по углу вокруг этой точки.
*   `bands`: Здесь используется сокращенная запись для одной полосы от белого к черному.
*   `start`: Точка начала градиента (нормализованные координаты внутри объекта). `{ x: 0.5, y: 0.5 }` — центр.
*   `shape`: Вектор направления. Для конического режима он определяет ось, от которой отсчитывается угол. `{ x: 0.5, y: 0 }` задает направление вправо от центра как нулевой угол.

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

Динамическая анимация в update()

Метод update() вызывается на каждом кадре игры. Здесь оживляются оба градиента с помощью синусоидальных функций от времени игры this.game.loop.time.

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)
    );
}
*   `this.bg.rotation`: Медленно вращает фоновый градиент, создавая ощущение глубины и движения.
*   `this.gradient.rotation`: Слегка покачивает основной конический градиент, меняя его начальную точку.
*   `this.gradient.setPosition(...)`: Плавно перемещает градиент по эллиптической траектории вокруг исходной точки (400, 300). Разные делители для `t` по осям X и Y делают движение более сложным и естественным.

Использование this.game.loop.time обеспечивает плавную и независимую от частоты кадров анимацию.

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

Конические симметричные градиенты в Phaser — это мощный инструмент для генерации динамических текстур, ауры вокруг объектов, стилизованных индикаторов или абстрактных фонов. Все вычисления происходят на GPU, что делает такие эффекты очень производительными. **Идеи для экспериментов:** 1. Замените CONIC_SYMMETRIC на CONIC_NONSYMMETRIC (shapeMode: 2) и посмотрите, как изменится поведение градиента. 2. Добавьте больше цветовых полос в массив bands конического градиента, чтобы создать радужный эффект. 3. Привяжите вращение или позицию градиента к игровой логике, например, к здоровью персонажа или углу поворота камеры. 4. Используйте несколько градиентов с режимами наложения (setBlendMode) для создания сложных композиций.