О чем этот пример
Визуальное оформление — ключевая часть игрового опыта. 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) для создания сложных композиций.
