О чем этот пример
Статичные фоны уходят в прошлое. Создание динамичных, дышащих текстур для игровых миров — ключ к погружению. В этой статье мы разберем, как с помощью объектов клеточного шума (Cellular Noise) в Phaser генерировать и анимировать сложные паттерны в реальном времени, имитируя природные материалы, магические эффекты или футуристические интерфейсы. Вы научитесь управлять 2D, 3D и 4D шумом, создавая бесконечную, плавно меняющуюся текстуру без использования тяжеловесных спрайтов или видео.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
noise1;
noise2;
noise3;
create()
{
const { width, height } = this.scale;
this.noise1 = this.add.noisecell2d({ noiseCells: [ 5, 9] }, width * 1 / 6, height / 2, width / 3, height);
this.noise2 = this.add.noisecell3d({ noiseCells: [ 5, 9, 1 ] }, width * 3 / 6, height / 2, width / 3, height);
this.noise3 = this.add.noisecell4d({ noiseCells: [ 5, 9, 1, 1 ] }, width * 5 / 6, height / 2, width / 3, height);
this.add.text(10, 10, '2D', { fontSize: 24 }).setStroke('#ff8844', 2).setShadow(2, 2, '#333333', 2, true, false);
this.add.text(width / 3 + 10, 10, '3D', { fontSize: 24 }).setStroke('#ff8844', 2).setShadow(2, 2, '#333333', 2, true, false);
this.add.text(width * 2 / 3 + 10, 10, '4D', { fontSize: 24 }).setStroke('#ff8844', 2).setShadow(2, 2, '#333333', 2, true, false);
}
update (time)
{
const t = time / 1000;
// Circular offset.
this.noise1.noiseOffset[0] = Math.cos(t);
this.noise1.noiseOffset[1] = Math.sin(t);
// Linear offset.
// Note that precision will eventually decay - you should loop the input.
this.noise2.noiseOffset[0] = t;
// Multi-dimensional offset.
this.noise3.noiseOffset[0] = t
this.noise3.noiseOffset[1] = Math.sin(t);
this.noise3.noiseOffset[2] = t
this.noise3.noiseOffset[3] = Math.sin(t);
}
}
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 1280,
height: 720,
scene: Example
};
const game = new Phaser.Game(config);
Создание объектов шума: 2D, 3D, 4D
В методе create() сцены создаются три визуальных объекта, представляющих разные измерения клеточного шума. Каждый объект размещается по горизонтали на своей трети экрана.
const { width, height } = this.scale;
this.noise1 = this.add.noisecell2d({ noiseCells: [ 5, 9] }, width * 1 / 6, height / 2, width / 3, height);
this.noise2 = this.add.noisecell3d({ noiseCells: [ 5, 9, 1 ] }, width * 3 / 6, height / 2, width / 3, height);
this.noise3 = this.add.noisecell4d({ noiseCells: [ 5, 9, 1, 1 ] }, width * 5 / 6, height / 2, width / 3, height);
* `this.add.noisecell2d/3d/4d` — фабричные методы для создания объектов шума. Число указывает на количество измерений, используемых при генерации паттерна. Больше измерений — сложнее и «глубже» результат.
* Параметр `noiseCells` — массив, определяющий базовую структуру ячеек. Значения `[5, 9]` для 2D шума задают количество "точек интереса" в паттерне, влияя на его зернистость и детализацию.
* Следующие аргументы — это X, Y координаты центра объекта, а затем его ширина и высота.
* Текстовые метки создаются с помощью `this.add.text` для визуального разделения примеров на экране.
Сердце анимации: метод update и массив noiseOffset
Динамика достигается в методе update(time), который вызывается каждый кадр. Ключевой инструмент — массив noiseOffset у каждого объекта шума. Смещая координаты в пространстве шума, мы создаем иллюзию движения самого паттерна.
update (time)
{
const t = time / 1000;
// Circular offset.
this.noise1.noiseOffset[0] = Math.cos(t);
this.noise1.noiseOffset[1] = Math.sin(t);
// Linear offset.
this.noise2.noiseOffset[0] = t;
// Multi-dimensional offset.
this.noise3.noiseOffset[0] = t
this.noise3.noiseOffset[1] = Math.sin(t);
this.noise3.noiseOffset[2] = t
this.noise3.noiseOffset[3] = Math.sin(t);
}
* time — время в миллисекундах с момента старта сцены. Делим на 1000, чтобы получить время `t` в секундах для плавных тригонометрических функций.
* this.noise1.noiseOffset[0] и [1] — управляют смещением по осям X и Y в 2D-пространстве шума. Использование Math.cos(t) и Math.sin(t) создает циклическое, круговое движение текстуры.
* Для 3D-шума (noise2) смещается только первое измерение ([0] = t), что дает эффект однонаправленного "прокручивания".
* 4D-шум (noise3) позволяет анимировать смещение по всем четырем измерениям, создавая наиболее сложную и органичную анимацию, где паттерн трансформируется по нескольким осям одновременно.
Практическое применение в играх
Клеточный шум — это не просто техническая демонстрация.
* **Фоны планет и ландшафтов:** Анимированный 2D/3D шум может изображать движущиеся облака в атмосфере газового гиганта, течения в океане или мерцающую поверхность звезды.
* **Магические и технологические эффекты:** Используйте 4D шум с цветовыми фильтрами (setTint) для создания поля энергии, щита или магического портала. Изменение параметра noiseCells на лету может имитировать нарастание или затухание силы.
* **Динамические текстуры объектов:** Назначайте объект шума как текстуру (setTexture) для спрайта, представляющего, например, кипящую жидкость в колбе или поврежденную броню.
// Пример: применение шума как текстуры к спрайту
let magicSphere = this.add.sprite(400, 300, '__WHITE');
magicSphere.setDisplaySize(200, 200);
// Предположим, noiseTexture — это рендер-текстура с нашим шумом
magicSphere.setTexture(noiseTexture);
magicSphere.setTint(0x00ffaa);
Оптимизация и важные замечания
Работа с шумом в реальном времени требует внимания к деталям.
1. **Точность и зацикливание:** Как отмечено в комментарии к 3D-примеру, при линейном увеличении смещения (noiseOffset[0] = t) точность числа с плавающей запятой со временем будет падать. Решение — реализовать логику зацикливания значения, когда оно превышает разумный предел (например, 1000), чтобы избежать артефактов при долгой работе игры.
2. **Производительность:** 4D шум — самый затратный. Используйте его точечно для ключевых визуальных эффектов. Для больших фоновых областей может быть достаточно 2D или 3D шума.
3. **Эксперименты с параметрами:** Массив noiseCells — мощный инструмент. Попробуйте значения [2, 3] для крупных, редких ячеек или [15, 20] для мелкой, почти однородной "песчаной" текстуры. Эффект меняется кардинально.
Что попробовать дальше
Объекты клеточного шума в Phaser открывают простой путь к созданию уникальных, производительных и бесшовно анимированных визуальных эффектов прямо в Canvas/WebGL. Вы можете управлять их сложностью, поведением и цветом, интегрируя в игровые миры как фон, так и интерфейсные элементы. Для экспериментов попробуйте: связать скорость noiseOffset с игровыми событиями (скорость корабля, уровень маны), комбинировать несколько слоев шума с разными режимами наложения (setBlendMode) или использовать шум как карту высот для простого vertex-смещения.
