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

По умолчанию Phaser 3 ограничивает количество активных источников света в сцене. Это сделано для производительности, но что, если вашей игре нужна сложная динамическая подсветка с десятками ламп? В этой статье вы узнаете, как просто увеличить этот лимит через конфиг игры и создадите анимированный световой тоннель из 20 движущихся источников. Управление лимитом света критически важно для игр с атмосферным подземельем, научно-фантастическими интерьерами или любыми сценами, где освещение — ключевая часть геймплея и визуальной эстетики.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('brick', [ 'assets/normal-maps/brick.jpg', 'assets/normal-maps/brick_n.png' ]);
    }

    create ()
    {
        this.add.image(400, 300, 'brick').setLighting(true);

        this.lights.enable().setAmbientColor(0x555555);

        const hsv = Phaser.Display.Color.HSVColorWheel();

        const radius = 80;
        const intensity = 6;
        let x = radius;
        let y = 0;

        //  To change the total number of lights see the Game Config object
        const maxLights = 20;

        //  Create a bunch of lights
        for (let i = 0; i < maxLights; i++)
        {
            const color = hsv[i * 10].color;

            const light = this.lights.addLight(x, y, radius, color, intensity);

            this.tweens.add({
                targets: light,
                y: 600,
                yoyo: true,
                repeat: -1,
                ease: 'Sine.easeInOut',
                duration: 2000,
                delay: i * 100
            });

            x += radius * 2;

            if (x > 800)
            {
                x = radius;
                y += radius;
            }
        }
    }
}

const config = {
    type: Phaser.WEBGL,
    width: 800,
    height: 600,
    parent: 'phaser-example',
    backgroundColor: '#000000',
    maxLights: 20,
    scene: Example
};

const game = new Phaser.Game(config);

Где и как задается лимит

Ключевой параметр maxLights задается не в коде сцены, а в главном конфигурационном объекте игры при ее создании. Это глобальная настройка для рендерера.

const config = {
    type: Phaser.WEBGL, // Для света обязателен WEBGL
    width: 800,
    height: 600,
    parent: 'phaser-example',
    backgroundColor: '#000000',
    maxLights: 20, // Вот этот параметр увеличивает лимит
    scene: Example
};

Важно помнить два условия: для работы системы света рендерер должен быть Phaser.WEBGL, а само освещение нужно явно включить в сцене с помощью this.lights.enable().

Подготовка объекта и включение света

Внутри сцены необходимо подготовить объект, который будет реагировать на свет, и активировать систему освещения.

preload() {
    this.load.image('brick', [ 'assets/normal-maps/brick.jpg', 'assets/normal-maps/brick_n.png' ]);
}

create() {
    // Добавляем изображение и включаем для него расчет освещения
    this.add.image(400, 300, 'brick').setLighting(true);
    // Включаем систему света и задаем Ambient Color
    this.lights.enable().setAmbientColor(0x555555);
}

Метод setLighting(true) сообщает рендереру, что при отрисовке этого изображения нужно учитывать источники света. А setAmbientColor устанавливает базовый цвет, который виден в тени, — без него неосвещенные участки будут полностью черными.

Создание множества динамических источников

Сердце примера — цикл, который создает массив источников света с разными цветами и анимирует их.

const hsv = Phaser.Display.Color.HSVColorWheel();
const maxLights = 20; // Используем значение из конфига

for (let i = 0; i < maxLights; i++) {
    // Берем цвет из HSV-палитры
    const color = hsv[i * 10].color;
    // Создаем точечный источник света
    const light = this.lights.addLight(x, y, radius, color, intensity);
}

Phaser.Display.Color.HSVColorWheel() генерирует палитру из 360 цветов, что позволяет легко получить радужный градиент. Метод this.lights.addLight(x, y, radius, color, intensity) создает источник в координатах (x, y) с заданным радиусом свечения, цветом и интенсивностью.

Анимация через Tween Manager

Чтобы свет не был статичным, каждый источник получает собственную анимацию с задержкой.

this.tweens.add({
    targets: light, // Анимируем конкретный источник
    y: 600,        // Конечная координата Y
    yoyo: true,    // Возврат обратно
    repeat: -1,    // Бесконечное повторение
    ease: 'Sine.easeInOut',
    duration: 2000,
    delay: i * 100 // Задержка для каждого следующего света
});

Использование delay: i * 100 создает эффект «волны»: источники начинают движение не одновременно, а один за другим. Tween Manager Phaser (this.tweens) позволяет легко анимировать любые свойства игровых объектов, включая созданные вручную, как наши источники света.

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

Увеличение maxLights в конфиге — простой способ значительно обогатить визуальную сложность сцены. Поэкспериментируйте: меняйте интенсивность (intensity) и радиус свечения, привязывайте источники света к движущимся спрайтам врагов или фонарей, используйте setAmbientColor для создания разного времени суток. Помните о балансе: каждый дополнительный источник света влияет на производительность, особенно на мобильных устройствах.