О чем этот пример
Создание процедурного контента — ключевой навык для разработчика игр. Вместо ручного рисования текстур или ландшафтов можно генерировать их алгоритмически, используя шум. Phaser 3 предоставляет встроенные объекты `NoiseSimplex2D` и `NoiseSimplex3D` для этой задачи. В этой статье мы разберем, как управлять параметрами шума — ячейками, периодом и итерациями — чтобы создавать разнообразные визуальные паттерны прямо в Canvas. Это полезно для генерации фонов, текстур поверхностей, карт высот и других динамических элементов игры.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create()
{
const { width, height } = this.scale;
this.add.noisesimplex2d({
noiseCells: [ 8, 9 ],
noisePeriod: [ 4, 3 ],
noiseIterations: 2
}, width / 4, height / 2, width / 2, height);
this.add.noisesimplex3d({
noiseCells: [ 8, 9, 8 ],
noisePeriod: [ 4, 3, 4 ],
noiseIterations: 2
}, 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);
}
}
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 1280,
height: 720,
scene: Example
};
const game = new Phaser.Game(config);
Что такое шум Simplex и зачем он нужен
Simplex-шум — это улучшенная версия классического шума Перлина. Он генерирует гладкие, естественно выглядящие псевдослучайные значения, которые идеально подходят для процедурной генерации. В отличие от случайных чисел, шум обладает связностью — соседние точки имеют похожие значения, что создает плавные переходы.
В Phaser эти объекты отображаются как текстуры в Canvas. 2D-шум создает двумерное изображение (например, облака или мрамор), а 3D-шум можно представить как "срез" трехмерного поля шума, что позволяет анимировать его, меняя Z-координату со временем.
Основные параметры для настройки:
- noiseCells: разрешение ячейки шума.
- noisePeriod: период (частота) шума.
- noiseIterations: количество октав (итераций) для добавления деталей.
Создание и размещение объектов шума
Объекты шума добавляются через фабрику this.add в методе create сцены. Важно правильно рассчитать позицию и размер, чтобы они поместились на экране.
const { width, height } = this.scale;
// Создание 2D шума
this.add.noisesimplex2d({
noiseCells: [ 8, 9 ],
noisePeriod: [ 4, 3 ],
noiseIterations: 2
}, width / 4, height / 2, width / 2, height);
Здесь width / 4, height / 2 — это координаты X и Y центра объекта. width / 2, height — его ширина и высота. Объект центрируется относительно заданной точки. Аналогично создается 3D-шум, но с тремя значениями в массивах параметров.
Расшифровка параметров: cells, period, iterations
Давайте детально разберем, что делает каждый параметр в конфигурационном объекте.
{
noiseCells: [ 8, 9 ],
noisePeriod: [ 4, 3 ],
noiseIterations: 2
}
- noiseCells: Определяет, на сколько виртуальных ячеек разбивается текстура по каждой оси. Значения [8, 9] означают 8 ячеек по X и 9 по Y. Это влияет на "зернистость" базового паттерна.
- noisePeriod: Задает период (длину волны) шума. Меньшие значения ([4, 3]) создают более частые, мелкие изменения, похожие на рябь. Большие значения дают более плавные, крупные волны.
- noiseIterations: Количество октав или слоев шума, которые накладываются друг на друга. Каждая следующая октава имеет более высокую частоту и меньшую амплитуду, добавляя детализацию. Значение `2` создает двухслойный шум.
Сравнение визуального результата: 2D vs 3D
В примере создаются два объекта рядом для наглядного сравнения. Код для 3D-шума почти идентичен, но использует трехмерные массивы.
this.add.noisesimplex3d({
noiseCells: [ 8, 9, 8 ],
noisePeriod: [ 4, 3, 4 ],
noiseIterations: 2
}, width * 3 / 4, height / 2, width / 2, height);
Визуально 3D-шум в статике может выглядеть очень похоже на 2D, так как отображается один его срез (при Z=0). Главное преимущество NoiseSimplex3D проявляется в анимации: со временем можно менять третью координату, создавая эффект плавно изменяющейся текстуры, подобный движущимся облакам или воде. Для добавления подписей используется this.add.text со стилизацией.
Идеи для практического применения в играх
Где можно использовать эту технику? Вот несколько конкретных идей:
1. **Динамические фоны:** Создайте бесшовный фоновый паттерн для космической игры или подводного уровня. 2. **Генерация рельефа:** Используйте значения шума как высоту (Y-координату) для вершин mesh или для создания карты высот в пиксель-арт стиле. 3. **Текстуры материалов:** Сгенерируйте основу для текстур дерева, камня или ржавчины, которую потом можно раскрасить. 4. **Визуальные эффекты:** Анимируйте 3D-шум для эффектов магического щита, искажения пространства или тумана.
// Пример: Анимация 3D шума (идея)
function update(time) {
if (noise3DObject) {
// Меняем Z-координату шума со временем
noise3DObject.setNoiseOffset(0, 0, Math.sin(time * 0.001));
}
}
Параметры noiseCells, noisePeriod и noiseIterations — ваши главные инструменты для контроля над видом генерируемого паттерна.
Что попробовать дальше
Встроенные объекты NoiseSimplex2D и NoiseSimplex3D в Phaser 3 открывают простой путь к процедурной генерации контента прямо в браузере. Поэкспериментируйте с параметрами: попробуйте увеличить noiseIterations до 4-5 для более детализированного "фрактального" вида, поиграйте с большими и малыми значениями noisePeriod или создайте несколько слоев шума с разными настройками и наложите их через blend-режимы. Это мощный фундамент для создания уникального визуала вашей игры без тяжеловесных внешних ассетов.
