О чем этот пример
Градиенты в Phaser 3 — это мощный инструмент визуализации, который часто используется для создания динамических фонов, эффектов освещения и абстрактных анимаций. Однако тонкости работы со смещением (`offset`) и формой (`shape`) могут привести к неожиданным и интересным артефактам, которые разработчики могут превратить в сознательные художественные приёмы. Эта статья разбирает пример кода, демонстрирующий, как разные режимы градиента (`BILINEAR`, `CONIC_SYMMETRIC`, `CONIC_ASYMMETRIC`) реагируют на анимированное смещение, и показывает, как управлять направлением конического градиента динамически.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
// Bilinear offset is mirrored.
const bilinear = this.add.gradient({
repeatMode: 2, // SAWTOOTH
shapeMode: 1, // BILINEAR
start: { x: 0.5, y: 0.5 },
shape: { x: 0.1, y: 0 },
bands: {
colorStart: 0xcccccc,
colorEnd: 0x8899cc,
}
}, 640, 360, 1280, 720);
this.bilinear = bilinear;
// Symmetric conic offset is kaleidoscopic,
// as the offset shifts the symmetry point.
const conicSymmetric = this.add.gradient({
repeatMode: 2, // SAWTOOTH
shapeMode: 3, // CONIC_SYMMETRIC
start: { x: 0.5, y: 0.5 },
shape: { x: 1, y: 0 },
bands: {
colorStart: 0xff8844,
colorEnd: 0x8844ff,
colorSpace: 1
}
}, 320, 256, 384, 384);
this.conicSymmetric = conicSymmetric;
Phaser.Actions.AddMaskShape(conicSymmetric, { useInternal: true, region: { x: 0, y: 0, width: 384, height: 384 } });
// Asymmetric conic is actually fine.
const conicAsymmetric = this.add.gradient({
repeatMode: 2, // SAWTOOTH
shapeMode: 4, // CONIC_ASYMMETRIC
start: { x: 0.5, y: 0.5 },
shape: { x: 1, y: 0 },
bands: {
colorStart: 0x44ff88,
colorEnd: 0xff8844,
colorSpace: 1
}
}, 960, 256, 384, 384);
this.conicAsymmetric = conicAsymmetric;
Phaser.Actions.AddMaskShape(conicAsymmetric, { useInternal: true, region: { x: 0, y: 0, width: 384, height: 384 } });
// You can instead reshape a symmetric conic gradient.
// See `update`.
const conicReshape = this.add.gradient({
repeatMode: 2, // SAWTOOTH
shapeMode: 3, // CONIC_SYMMETRIC
start: { x: 0.5, y: 0.5 },
shape: { x: 1, y: 0 },
bands: {
colorStart: 0xffcc44,
colorEnd: 0x4488ff,
colorSpace: 1
}
}, 640, 512, 384, 384);
this.conicReshape = conicReshape;
Phaser.Actions.AddMaskShape(conicReshape, { useInternal: true, region: { x: 0, y: 0, width: 384, height: 384 } });
}
update (time)
{
this.bilinear.offset = time / 1000;
this.conicSymmetric.offset = time / 1000;
this.conicAsymmetric.offset = time / 1000;
// Reshape symmetric cone gradient to point in a different direction.
// Shape is a Vector2 so supports many useful methods.
this.conicReshape.shape.setAngle(time * Math.PI / 1000);
}
}
const config = {
type: Phaser.WEBGL,
width: 1280,
height: 720,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Основа: создание градиента с помощью `this.add.gradient`
Основной метод для создания градиентного игрового объекта — this.add.gradient. Он принимает объект конфигурации, позицию (x, y) и размеры (width, height). Ключевые параметры конфигурации:
- repeatMode: режим повторения. В примере используется `2(Phaser.Gradient.GradientRepeatMode.SAWTOOTH`).
- shapeMode: определяет математическую форму градиента.
- start: точка начала градиента в нормализованных координатах (от 0 до 1).
- shape: вектор, задающий направление или форму градиента.
- bands: объект с настройками цветовых полос (colorStart, colorEnd, colorSpace).
Создадим базовый билинейный градиент:
const bilinear = this.add.gradient({
repeatMode: 2, // SAWTOOTH
shapeMode: 1, // BILINEAR
start: { x: 0.5, y: 0.5 },
shape: { x: 0.1, y: 0 },
bands: {
colorStart: 0xcccccc,
colorEnd: 0x8899cc,
}
}, 640, 360, 1280, 720);
Эффект зеркального смещения в билинейном градиенте
В примере свойству bilinear.offset в методе update присваивается значение, зависящее от времени. Это заставляет текстуру градиента «прокручиваться». Однако из-за особенностей режима SAWTOOTH и формы BILINEAR смещение приводит к зеркальному эффекту, а не к плавному линейному сдвигу. Градиент как бы отражается от своих границ. Это поведение встроено в шейдер, который рассчитывает цвет для этой конкретной формы (shapeMode).
Код анимации смещения:
this.bilinear.offset = time / 1000;
Здесь time — это время в миллисекундах, передаваемое в update. Деление на 1000 замедляет анимацию, делая её видимой глазу.
Калидоскопический эффект в симметричном коническом градиенте
Симметричный конический градиент (CONIC_SYMMETRIC) создаёт узор, симметричный относительно точки начала (start). Когда мы применяем смещение (offset), эта точка симметрии сдвигается, что приводит к калейдоскопическому, вращающемуся эффекту. В примере градиент обрезается маской с помощью Phaser.Actions.AddMaskShape для создания аккуратного квадратного вида.
Создание и маскирование градиента:
const conicSymmetric = this.add.gradient({
repeatMode: 2,
shapeMode: 3, // CONIC_SYMMETRIC
start: { x: 0.5, y: 0.5 },
shape: { x: 1, y: 0 },
bands: {
colorStart: 0xff8844,
colorEnd: 0x8844ff,
colorSpace: 1
}
}, 320, 256, 384, 384);
Phaser.Actions.AddMaskShape(conicSymmetric, { useInternal: true, region: { x: 0, y: 0, width: 384, height: 384 } });
Анимация смещения выполняется аналогично: this.conicSymmetric.offset = time / 1000;.
Стабильность асимметричного конического градиента
В отличие от симметричного, асимметричный конический градиент (CONIC_ASYMMETRIC) не демонстрирует калейдоскопического разрыва при смещении. Его структура более устойчива, и смещение приводит к предсказуемому, плавному вращению цветовых полос. Это делает его хорошим выбором для создания непрерывных вращающихся эффектов без визуальных артефактов.
Код создания идентичен, за исключением shapeMode: 4:
shapeMode: 4, // CONIC_ASYMMETRIC
Динамическое изменение направления градиента через свойство `shape`
Свойство shape градиента — это объект Phaser.Math.Vector2. Это позволяет не только задать начальное направление, но и динамически менять его, используя методы вектора. В примере для объекта conicReshape в update вызывается this.conicReshape.shape.setAngle(...). Это вращает вектор направления градиента, заставляя весь конический узор плавно поворачиваться вокруг точки start.
this.conicReshape.shape.setAngle(time * Math.PI / 1000);
Метод setAngle устанавливает угол вектора в радианах. Умножение time на Math.PI / 1000 создаёт медленное непрерывное вращение. Это более контролируемый способ анимации, чем изменение offset, и он не вызывает нежелательных артефактов в симметричном режиме.
Что попробовать дальше
Смещение и форма градиентов в Phaser 3 открывают пространство для экспериментов. Зеркальный эффект BILINEAR и калейдоскопический CONIC_SYMMETRIC можно использовать для создания психоделических фонов или эффектов искажения. Для плавных вращений лучше подходит CONIC_ASYMMETRIC или прямое управление вектором shape. Попробуйте комбинировать анимацию offset и shape, применять разные colorSpace для нелинейных цветовых переходов или накладывать несколько градиентов с режимами наложения (blendMode) для создания сложных визуальных текстур.
