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

Визуальные эффекты часто требуют дорогостоящих текстур и анимаций. Клеточный шум (Cellular Noise) в Phaser решает эту проблему, генерируя паттерны программно. Этот подход экономит ресурсы, позволяет создавать уникальные фоны, текстуры материалов и динамические эффекты в реальном времени без загрузки внешних файлов. В статье разберемся, как использовать `add.noisecell2d` для ваших проектов.

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class Example extends Phaser.Scene
{
    noise1;
    noise2;
    noise3;

    create()
    {
        const { width, height } = this.scale;

        const config = {
            noiseCells: [ 5, 9 ],
            noiseColorStart: 0xffffff,
            noiseColorEnd: [ 0, 0, 0, 0 ]
        };

        // Create cell patterns at different cell grid sizes and aspect ratios.
        // Note that there is no performance difference.

        this.noise1 = this.add.noisecell2d(config, width * 1 / 6, height / 2, width / 3, height);
        this.noise2 = this.add.noisecell2d({
            ...config,
            noiseCells: [ 5, 90 ]
        }, width * 3 / 6, height / 2, width / 3, height);
        this.noise3 = this.add.noisecell2d({
            ...config,
            noiseCells: [ 50, 90 ]
        }, width * 5 / 6, height / 2, width / 3, height);

        this.add.text(10, 10, '5x9 cells', { fontSize: 24 }).setStroke('#ff8844', 2).setShadow(2, 2, '#333333', 2, true, false);
        this.add.text(width / 3 + 10, 10, '5x90 cells', { fontSize: 24 }).setStroke('#ff8844', 2).setShadow(2, 2, '#333333', 2, true, false);
        this.add.text(width * 2 / 3 + 10, 10, '50x90 cells', { fontSize: 24 }).setStroke('#ff8844', 2).setShadow(2, 2, '#333333', 2, true, false);
    }

    update (time)
    {
        const t = time / 10000;
        const c = Math.cos(t);
        const s = Math.sin(t);

        this.noise1.noiseOffset[0] = c;
        this.noise1.noiseOffset[1] = s;
        this.noise2.noiseOffset[0] = c;
        this.noise2.noiseOffset[1] = s;
        this.noise3.noiseOffset[0] = c;
        this.noise3.noiseOffset[1] = s;
    }
}

const config = {
    type: Phaser.WEBGL,
    parent: 'phaser-example',
    width: 1280,
    height: 720,
    scene: Example
};

const game = new Phaser.Game(config);

Что такое клеточный шум?

Клеточный шум — это тип процедурной генерации, создающий текстуру, разбитую на ячейки (клетки). Каждая ячейка заполняется градиентом между двумя цветами на основе шумовой функции. Главное преимущество — полный контроль над размером сетки, цветами и анимацией через код.

В Phaser для этого используется игровой объект Noise2D, создаваемый фабричным методом this.add.noisecell2d. Он рендерится на GPU, поэтому изменение параметров в реальном времени не влияет на производительность.

Разбираем конфигурацию

Основные параметры передаются в объекте конфигурации. Ключевые свойства: - noiseCells: массив [x, y] определяет количество ячеек по горизонтали и вертикали. - noiseColorStart: начальный цвет градиента в ячейке (может быть числом 0xffffff или массивом RGBA). - noiseColorEnd: конечный цвет градиента.

const config = {
    noiseCells: [ 5, 9 ],
    noiseColorStart: 0xffffff,
    noiseColorEnd: [ 0, 0, 0, 0 ]
};

В примере noiseColorEnd задан массивом [0, 0, 0, 0], что соответствует полностью прозрачному черному цвету. Градиент будет плавно уходить в прозрачность.

Создание и размещение объектов

Метод this.add.noisecell2d принимает конфиг, позиции X, Y и размеры. В примере создается три объекта с разной плотностью сетки, но одинаковыми размерами.

this.noise1 = this.add.noisecell2d(config, width * 1 / 6, height / 2, width / 3, height);

Обратите внимание на использование оператора spread { ...config, noiseCells: [ 5, 90 ] } для создания нового конфига на основе старого. Это удобно для переопределения только нужных параметров.

Текстовые метки создаются стандартным методом this.add.text и позиционируются относительно областей шума.

Анимируем смещение шума

Динамика достигается изменением свойства noiseOffset объекта шума в методе update. Это двумерный массив, смещающий точку отсчета шумовой функции.

update (time)
{
    const t = time / 10000;
    const c = Math.cos(t);
    const s = Math.sin(t);

    this.noise1.noiseOffset[0] = c;
    this.noise1.noiseOffset[1] = s;
}

Здесь time (время с начала работы сцены) делится на 10000 для замедления анимации. Значения косинуса и синуса создают плавное циклическое движение паттерна внутри каждой ячейки. Изменение noiseOffset не пересоздает текстуру, а лишь меняет параметры шейдера, что очень быстро.

Практические применения

1. **Фоны и атмосфера**: Создавайте бесшовные прокручивающиеся фоны для космоса, воды или облаков, анимируя noiseOffset. 2. **Генерация рельефа**: Используйте как карту высот для процедурной генерации ландшафта (например, через маску). 3. **Динамические материалы**: Имитируйте металлические блики, рябь на воде или дымку, комбинируя несколько слоев шума с разными noiseCells. 4. **Эффекты затемнения/осветления**: Плавные переходы с прозрачностью, как в примере, идеальны для создания вуалей или затемненных областей UI.

Важно: поскольку объект является наследником Phaser.GameObjects.Image, к нему применимы все стандартные трансформации — setAlpha, setTint, setScale.

Что попробовать дальше

Клеточный шум в Phaser — это мощный и производительный инструмент для процедурной графики. Он позволяет создавать сложные визуальные эффекты без растровых текстур. Для экспериментов попробуйте: - менять цвета градиента в зависимости от игровых событий; - привязать noiseCells к размеру экрана для адаптивности; - комбинировать несколько слоев шума с режимами смешивания (setBlendMode).