О чем этот пример
Визуальные эффекты на основе процедурного шума — мощный инструмент для создания атмосферы в играх: от мерцающих энергетических полей до таинственных туманов. Phaser 3 предоставляет встроенные объекты `NoiseSimplex2D` и `NoiseSimplex3D`, которые генерируют текстуры шума прямо на GPU, что позволяет создавать сложные анимированные фоны без использования внешних изображений. В этой статье мы разберем, как настроить и анимировать эти объекты, управляя их параметрами в реальном времени для создания гипнотических потоковых эффектов.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
noise2d;
noise3d;
create()
{
const { width, height } = this.scale;
this.noise2d = this.add.noisesimplex2d({
noiseCells: [ 8, 9 ],
noiseIterations: 3,
noiseColorStart: 0xffaa88,
noiseColorEnd: 0x442266
}, width / 4, height / 2, width / 2, height);
this.noise3d = this.add.noisesimplex3d({
noiseCells: [ 8, 9, 4 ],
noiseIterations: 3,
noiseColorStart: 0x22dd22,
noiseColorEnd: 0x662244
}, width * 3 / 4, height / 2, width / 2, height);
this.add.text(10, 10, '2D', { fontSize: 24 }).setStroke('#ff8844', 2).setShadow(2, 2, '#333333', 2, true, false);
this.add.text(width / 2 + 10, 10, '3D', { fontSize: 24 }).setStroke('#ff8844', 2).setShadow(2, 2, '#333333', 2, true, false);
}
update (time)
{
// Prevent long-term precision loss.
// Flow is cyclic, every 2PI radians.
const t = (time / 1000) % (Math.PI * 2);
this.noise2d.noiseFlow = t;
this.noise3d.noiseFlow = t;
}
}
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 1280,
height: 720,
scene: Example
};
const game = new Phaser.Game(config);
Создание объектов шума: 2D и 3D
Класс Example расширяет Phaser.Scene и создаёт два визуальных объекта шума в методе create(). Один использует двумерный, а другой — трёхмерный симплекс-шум. Ключевая разница в измерении шума влияет на визуальную сложность и характер движения.
Для создания объекта используется фабричный метод this.add.noisesimplex2d() (или noisesimplex3d()). Первым параметром передаётся конфигурационный объект, а следующие четыре аргумента задают позицию (x, y) и размеры (width, height) прямоугольной области, в которой будет отрисован шум.
this.noise2d = this.add.noisesimplex2d({
noiseCells: [ 8, 9 ],
noiseIterations: 3,
noiseColorStart: 0xffaa88,
noiseColorEnd: 0x442266
}, width / 4, height / 2, width / 2, height);
Конфигурация: ячейки, итерации и цвета
Конфигурационный объект позволяет тонко настроить внешний вид шума.
* noiseCells: Массив, определяющий детализацию. Для 2D шума это [x, y], для 3D — [x, y, z]. Меньшие значения дают более крупные, размазанные "ячейки" шума, большие — более мелкую и частую текстуру.
* noiseIterations: Количество наложений (октав) шума. Больше итераций увеличивает детализацию и контрастность текстуры.
* noiseColorStart и noiseColorEnd: Цвета в формате HEX (например, 0xffaa88), между которыми интерполируется итоговая текстура. Они задают цветовую палитру визуализации.
{
noiseCells: [ 8, 9, 4 ], // 3D: 8 по X, 9 по Y, 4 по Z
noiseIterations: 3,
noiseColorStart: 0x22dd22,
noiseColorEnd: 0x662244
}
Анимация через свойство noiseFlow
Статичный шум — это лишь половина возможностей. Динамика создаётся в методе update(), который вызывается на каждом кадре.
Свойство noiseFlow объектов noise2d и noise3d управляет "потоком" или фазой шума. Изменяя это значение со временем, мы заставляем текстуру плавно перетекать и видоизменяться, создавая иллюзию движения, подобного текущей жидкости или полю энергии.
В примере для анимации используется время игры (time), которое преобразуется в циклическое значение. Операция модуля % (Math.PI * 2) гарантирует, что значение noiseFlow будет циклически повторяться в диапазоне от 0 до ~6.283, предотвращая переполнение и потерю точности при долгой работе.
update (time)
{
const t = (time / 1000) % (Math.PI * 2);
this.noise2d.noiseFlow = t;
this.noise3d.noiseFlow = t;
}
Сравнение визуала 2D и 3D шума
Разместив оба объекта на сцене, можно сразу увидеть разницу. 2D шум (noiseCells: [8, 9]) создаёт более плоский, слоистый узор, который "течёт" в двух измерениях. 3D шум (noiseCells: [8, 9, 4]) использует третье измерение (Z) как дополнительную ось вариативности, что даёт более объёмный, сложный и органичный рисунок, напоминающий клубящийся дым или мрамор.
Именно третье измерение в конфигурации noiseCells и делает визуал 3D объекта богаче. Анимация noiseFlow по сути "пролистывает" срезы этого трёхмерного поля шума, создавая непрерывную трансформацию.
// 2D шум — плоский, волнообразный
this.add.text(10, 10, '2D', { fontSize: 24 });
// 3D шум — объёмный, турбулентный
this.add.text(width / 2 + 10, 10, '3D', { fontSize: 24 });
Что попробовать дальше
Объекты NoiseSimplex2D/3D в Phaser — это готовый и производительный способ добавить в игру "живые" фоны, эффекты магии, помех или природных явлений. Для экспериментов попробуйте:
1. Связывать noiseFlow не со временем, а с положением игрока, создавая реактивное поле вокруг него.
2. Использовать несколько слоёв шума с разными noiseCells и цветами, наложенными с режимами смешивания (setBlendMode).
3. Динамически менять noiseColorStart и noiseColorEnd в ответ на события в игре для визуальной обратной связи.
