О чем этот пример

Создание процедурного контента — ключевой навык для разработчика игр. Вместо ручного рисования текстур или ландшафтов можно генерировать их алгоритмически, используя шум. 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-режимы. Это мощный фундамент для создания уникального визуала вашей игры без тяжеловесных внешних ассетов.