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

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

Версия 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('egg', 'assets/sprites/dragonegg.png');
    }

    create ()
    {
        this.add.sprite(200, 300, 'egg');

        const egg = this.add.sprite(600, 300, 'egg');

        const fx = egg.enableFilters().filters.internal.addColorMatrix().colorMatrix;

        this.add.text(10, 10, 'Click to change ColorMatrix function');

        const text = this.add.text(400, 550, 'Default').setOrigin(0.5, 0.5);

        let effect = 0;

        this.input.on('pointerdown', () => {

            effect++;

            if (effect === 18)
            {
                effect = 0;
            }

            if (effect === 0)
            {
                text.setText('Default');
                fx.reset();
            }
            else if (effect === 1)
            {
                text.setText('brightness(1.2)');
                fx.brightness(1.2);
            }
            else if (effect === 2)
            {
                text.setText('saturate(2.5)');
                fx.saturate(2.5);
            }
            else if (effect === 3)
            {
                text.setText('hue(40)');
                fx.hue(40);
            }
            else if (effect === 4)
            {
                text.setText('grayscale(1)');
                fx.grayscale(1);
            }
            else if (effect === 5)
            {
                text.setText('night()');
                fx.night();
            }
            else if (effect === 6)
            {
                text.setText('contrast(1)');
                fx.contrast(1);
            }
            else if (effect === 7)
            {
                text.setText('negative()');
                fx.negative();
            }
            else if (effect === 8)
            {
                text.setText('blackWhite()');
                fx.blackWhite();
            }
            else if (effect === 9)
            {
                text.setText('lsd()');
                fx.lsd();
            }
            else if (effect === 10)
            {
                text.setText('desaturateLuminance()');
                fx.desaturateLuminance();
            }
            else if (effect === 11)
            {
                text.setText('sepia()');
                fx.sepia();
            }
            else if (effect === 12)
            {
                text.setText('brown()');
                fx.brown();
            }
            else if (effect === 13)
            {
                text.setText('vintagePinhole()');
                fx.vintagePinhole();
            }
            else if (effect === 14)
            {
                text.setText('kodachrome()');
                fx.kodachrome();
            }
            else if (effect === 15)
            {
                text.setText('technicolor()');
                fx.technicolor();
            }
            else if (effect === 16)
            {
                text.setText('polaroid()');
                fx.polaroid();
            }
            else if (effect === 17)
            {
                text.setText('shiftToBGR()');
                fx.shiftToBGR();
            }

        });
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#2d2d66',
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

Подготовка сцены и создание спрайтов

В начале примера, в методе preload(), загружается текстура яйца дракона. Это стандартная практика для Phaser.

В методе create() создаются два спрайта с этой текстурой. Первый отображается без изменений, а ко второму мы применим фильтры. Это наглядно демонстрирует разницу между оригиналом и обработанным изображением.

this.add.sprite(200, 300, 'egg');
const egg = this.add.sprite(600, 300, 'egg');

Активация фильтров и создание ColorMatrix

Ключевой момент — добавление фильтра к спрайту. Метод enableFilters() активирует систему фильтров для игрового объекта. Далее мы получаем доступ к внутреннему списку фильтров (filters.internal) и добавляем новый фильтр типа ColorMatrix с помощью addColorMatrix().

Свойство colorMatrix возвращает ссылку на сам объект матрицы, который содержит все методы для манипуляций с цветом.

const fx = egg.enableFilters().filters.internal.addColorMatrix().colorMatrix;

Управление эффектами по клику

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

Внутри обработчика события переменная-счетчик effect увеличивается, а затем в блоке if/else вызывается соответствующий метод объекта fx (нашей ColorMatrix).

let effect = 0;
this.input.on('pointerdown', () => {
    effect++;
    if (effect === 18) { effect = 0; }
    if (effect === 0) {
        text.setText('Default');
        fx.reset(); // Сбрасывает матрицу в исходное состояние
    }
    else if (effect === 1) {
        text.setText('brightness(1.2)');
        fx.brightness(1.2); // Увеличивает яркость на 20%
    }
    // ... остальные условия
});

Быстрые пресеты и базовые операции

ColorMatrix предлагает два типа методов: базовые операции (как brightness, saturate, hue) и готовые стилизованные пресеты.

- **Базовые операции** принимают числовые значения для тонкой настройки. - **Готовые пресеты** (как sepia(), negative(), night()) применяют сложные, заранее настроенные матрицы для создания конкретного визуального стиля.

Метод reset() полностью очищает все примененные изменения, возвращая спрайт к исходному виду.

fx.grayscale(1);    // Полное обесцвечивание
fx.contrast(1);     // Увеличение контрастности
fx.lsd();           // Психоделический эффект
fx.shiftToBGR();    // Инверсия цветовых каналов (RGB -> BGR)

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

ColorMatrix — это ваш швейцарский нож для работы с цветом в Phaser. Вы можете использовать его не только для эстетики, но и для геймдизайна: например, применять эффект grayscale() к побежденным врагам, night() для смены времени суток в игре или hue() для мигания объектов предупреждения. Для экспериментов попробуйте комбинировать эффекты, вызывая несколько методов подряд, или анимировать параметры (например, плавно менять яркость) в методе update() сцены.