О чем этот пример
Визуальные эффекты на основе процедурного шума — мощный инструмент для создания динамичных фонов, текстур и атмосферных явлений в играх. Phaser предоставляет встроенные объекты для генерации клеточного шума в 2D, 3D и даже 4D пространствах. В этой статье мы разберем, как управлять дополнительными измерениями шума, чтобы создавать анимированные, «живые» текстуры прямо во время выполнения игры, без использования спрайт-листов или видеороликов.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
noise2;
noise3;
create()
{
const { width, height } = this.scale;
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)
{
// Scroll the Z axis.
// Note that this will lose precision once it reaches high values.
const t = time / 5000;
// 2D noise has no extra dimension to offset.
this.noise2.noiseOffset[2] = t;
this.noise3.noiseOffset[2] = t;
}
}
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 1280,
height: 720,
scene: Example
};
const game = new Phaser.Game(config);
Создание объектов шума: от 2D к 4D
В методе create() сцены создаются три объекта шума, которые визуализируются как текстуры. Ключевое различие между ними — количество измерений.
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);
Каждый вызов метода (noisecell2d, noisecell3d, noisecell4d) создает новый игровой объект типа Noise. Параметр noiseCells — это массив, определяющий детализацию шума в каждом измерении. Например, [5, 9] для 2D означает 5 ячеек по X и 9 по Y. Последующие вызовы добавляют параметры для Z и W осей.
Объекты размещаются на экране друг за другом (на 1/6, 3/6 и 5/6 ширины экрана). Важно, что 3D и 4D объекты сохраняются в свойства класса (this.noise2, this.noise3), чтобы к ним можно было обращаться позже в цикле обновления. 2D-шум не анимируется, поэтому ссылка на него не сохраняется.
Анимация через смещение по оси Z
Динамика эффекту придается в методе update(time). Этот метод вызывается на каждом кадре игры и получает текущее игровое время в миллисекундах.
const t = time / 5000;
Здесь время делится на 5000, чтобы замедлить изменение и сделать анимацию плавной. Переменная `t` постепенно увеличивается с каждой секундой игры.
this.noise2.noiseOffset[2] = t;
this.noise3.noiseOffset[2] = t;
Свойство noiseOffset есть у объектов 3D и 4D шума. Это массив, где индексы 0, 1, 2 соответствуют смещению по осям X, Y, Z соответственно. Присваивая значение `tиндексу[2]`, мы непрерывно сдвигаем «срез» шума по оси Z. Визуально это создает эффект плавного, бесшовного скроллинга текстуры. Для 4D-шума это работает аналогично, так как четвертое измерение (W) остается статичным.
Важное замечание из кода: при очень больших значениях `t` может произойти потеря точности вычислений, что потенциально скажется на визуальном качестве.
Практическое применение и настройка
Где это можно использовать? Анимированный 3D/4D шум идеально подходит для: * Фоновых переливов (лава, туман, вода). * Генерации динамических текстур для магии или щитов. * Создания «живых» поверхностей планет или астероидов.
Экспериментируйте с параметрами:
// Увеличение детализации (больше ячеек)
{ noiseCells: [10, 20, 3] }
// Анимация по другой оси или с другой скоростью
this.noise2.noiseOffset[0] = time / 10000; // Медленный скролл по X
// Одновременное движение по нескольким осям
this.noise3.noiseOffset[1] = time / 7000;
this.noise3.noiseOffset[2] = time / 5000;
Изменяя массив noiseCells, вы контролируете «зернистость» паттерна. Меньшие значения дают крупные, четкие ячейки, большие — мелкую, сложную текстуру. Комбинируя скорости смещения по разным осям, можно получить сложные, не повторяющиеся анимации.
Что попробовать дальше
Использование многомерного клеточного шума в Phaser открывает простой путь к созданию производительных и визуально интересных динамических эффектов прямо в коде. Вы управляете анимацией через смещение в дополнительном измерении, что эффективнее, чем проигрывание спрайт-листа.
Для экспериментов попробуйте:
1. Привязать смещение noiseOffset не ко времени, а к скорости игрового персонажа, чтобы шум на фоне реагировал на движение.
2. Использовать 4D-шум, анимируя и третье измерение (noiseOffset[3]), для получения еще более сложных трансформаций.
3. Наложить на шум цветовой градиент через шейдер для создания эффекта плазмы или энергетического поля.
