О чем этот пример
Визуальные эффекты — мощный инструмент для создания атмосферы и выделения объектов в игре. В этом примере мы разберем, как с помощью фильтров Phaser выделить определенный цвет на спрайте и полностью изменить его оттенок и яркость. Этот прием полезен для создания визуальных подсказок, трансформации врагов или динамической смены времени суток на уже готовых ассетах, не требуя их перерисовки.
Версия 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('bg', 'assets/pics/fairy-background-craft-pixel.png');
this.load.image('sprite', 'assets/rope/dragonball.png');
}
create ()
{
const bg = this.add.image(400, 200, 'bg').setScale(2);
this.spriteBase = this.add.image(240, 420, 'sprite').setFlipX(true);
this.spriteKey = this.add.image(1000, 400, 'sprite').enableFilters();
// Isolate the blue uniform and turn it saffron.
const parallelFilters = this.spriteKey.filters.internal.addParallelFilters();
const keyRed = parallelFilters.top.addKey({
color: 0x241cb4,
isolate: true,
threshold: 0.4
});
const colorMatrix = parallelFilters.top.addColorMatrix();
colorMatrix.colorMatrix.hue(150).brightness(2,true);
}
}
const config = {
type: Phaser.WEBGL,
width: 1280,
height: 720,
backgroundColor: '#2d3440',
smoothPixelArt: true,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и загрузка ресурсов
В методе preload мы загружаем два изображения с удаленного сервера, установив базовый URL. Это фон и основной спрайт, с которым будем работать.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/pics/fairy-background-craft-pixel.png');
this.load.image('sprite', 'assets/rope/dragonball.png');
}
В методе create мы размещаем фон и два экземпляра одного и того же спрайта. Первый спрайт (spriteBase) отображается в оригинале, а для второго (spriteKey) мы включаем возможность применения фильтров с помощью метода .enableFilters(). Это обязательный шаг перед добавлением любых фильтров к объекту.
create ()
{
const bg = this.add.image(400, 200, 'bg').setScale(2);
this.spriteBase = this.add.image(240, 420, 'sprite').setFlipX(true);
this.spriteKey = this.add.image(1000, 400, 'sprite').enableFilters();
}
Создание параллельных фильтров
Фильтры в Phaser можно комбинировать. В данном примере мы создаем группу параллельных фильтров для спрайта spriteKey. Параллельные фильтры применяются к изображению одновременно, а не последовательно. Мы получаем доступ к внутренней системе фильтров объекта через this.spriteKey.filters.internal.
const parallelFilters = this.spriteKey.filters.internal.addParallelFilters();
Метод addParallelFilters() возвращает контейнер, внутри которого мы можем добавлять конкретные фильтры. В данном случае мы будем работать с верхним слоем (parallelFilters.top).
Фильтр Key: выделение целевого цвета
Первый фильтр, который мы добавляем — Key. Его задача — найти на изображении все пиксели, близкие к заданному цвету, и изолировать их.
const keyRed = parallelFilters.top.addKey({
color: 0x241cb4,
isolate: true,
threshold: 0.4
});
Разберем параметры:
- color: 0x241cb4 — целевой цвет в HEX-формате, который мы хотим выделить (в данном случае темно-синий).
- isolate: true — ключевой параметр. Он указывает фильтру оставить только пиксели целевого цвета, а все остальные сделать прозрачными или невидимыми.
- threshold: 0.4 — порог чувствительности (от 0 до 1). Чем выше значение, тем более широкий диапазон оттенков, близких к целевому цвету, будет захвачен фильтром. Значение 0.4 дает умеренную чувствительность.
Фильтр Color Matrix: трансформация цвета
После того как мы изолировали пиксели нужного цвета, можно их преобразовать. Для этого добавляется фильтр ColorMatrix, который предоставляет матрицу для комплексных цветовых преобразований.
const colorMatrix = parallelFilters.top.addColorMatrix();
colorMatrix.colorMatrix.hue(150).brightness(2, true);
Метод hue(150) поворачивает цветовой круг на 150 градусов. Это кардинально меняет оттенок выделенных синих пикселей (например, на оранжевый или желтый).
Метод brightness(2, true) увеличивает яркость. Первый аргумент — множитель (2 означает удвоение яркости). Второй аргумент true указывает, что яркость применяется ко всем каналам (R, G, B) равномерно, сохраняя цветовой баланс.
Поскольку фильтры добавлены параллельно в один слой (parallelFilters.top), они применяются к исходному изображению одновременно, но логически: сначала Key выделяет область, а ColorMatrix меняет ее свойства.
Настройка конфигурации игры
Весь эффект работает благодаря использованию WebGL-рендерера. Важно указать type: Phaser.WEBGL в конфигурации игры, так как фильтры не поддерживаются на Canvas-рендерере.
const config = {
type: Phaser.WEBGL,
width: 1280,
height: 720,
backgroundColor: '#2d3440',
smoothPixelArt: true,
parent: 'phaser-example',
scene: Example
};
Параметр smoothPixelArt: true помогает сгладить пиксельную графику при масштабировании, что улучшает визуальное качество. backgroundColor задает темный фон для контраста с яркими спрайтами.
Что попробовать дальше
Комбинация фильтров Key и ColorMatrix открывает быстрый путь для программного ретекстуринга объектов в игре. Вы можете динамически менять цвета униформы команд, подсвечивать интерактивные элементы или создавать эффекты проклятья или благословения, трансформируя внешний вид персонажей. Для экспериментов попробуйте изменить параметр threshold у Key фильтра, чтобы захватить больше или меньше оттенков, или используйте другие методы colorMatrix, например .saturate() или .contrast(), для создания разнообразных визуальных стилей.
