О чем этот пример
Режимы наложения (Blend Modes) — мощный инструмент для создания визуальных эффектов в 2D-графике. Они позволяют контролировать, как пиксели одного графического объекта (спрайта, изображения) взаимодействуют с пикселями под ним. В этой статье мы разберем пример использования режима `DIFFERENCE` в Phaser.js и научимся управлять визуальным слоем игры, создавая динамичные и стильные сцены. Это полезно для выделения UI-элементов, создания неоновых эффектов, частиц с «вычитающим» свечением или просто для добавления глубины игровому миру.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
// Difference is Canvas Blend Modes
class Example extends Phaser.Scene
{
constructor ()
{
super();
this.sprites = [];
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/skies/space1.png');
this.load.image('particle', 'assets/particles/yellow.png');
this.load.image('logo', 'assets/sprites/phaser2.png');
}
create ()
{
this.add.image(400, 300, 'bg');
// Create the particles
for (var i = 0; i < 300; i++)
{
const x = Phaser.Math.Between(-64, 800);
const y = Phaser.Math.Between(-64, 600);
const image = this.add.image(x, y, 'particle');
// Canvas and WebGL:
// NORMAL
// ADD
// MULTIPLY
// SCREEN
// Canvas only:
// OVERLAY
// DARKEN
// LIGHTEN
// COLOR_DODGE
// COLOR_BURN
// HARD_LIGHT
// SOFT_LIGHT
// DIFFERENCE
// EXCLUSION
// HUE
// SATURATION
// COLOR
// LUMINOSITY
// image.setBlendMode(Phaser.BlendModes.OVERLAY);
image.setBlendMode(Phaser.BlendModes.ADD);
this.sprites.push({ s: image, r: 2 + Math.random() * 6 });
}
this.add.image(400, 300, 'logo').setBlendMode(Phaser.BlendModes.DIFFERENCE);
}
update ()
{
for (var i = 0; i < this.sprites.length; i++)
{
const sprite = this.sprites[i].s;
sprite.y -= this.sprites[i].r;
if (sprite.y < -256)
{
sprite.y = 700;
}
}
}
}
const config = {
type: Phaser.CANVAS,
width: 800,
height: 600,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое Blend Modes и зачем они нужны?
Режимы наложения определяют математическую формулу, по которой цвет рисуемого пикселя (источник) комбинируется с цветом пикселя, уже находящегося в буфере кадра (цель). В отличие от простой прозрачности (alpha), они могут создавать более сложные и интересные визуальные взаимодействия: сложение цветов (ADD), умножение (MULTIPLY), наложение экрана (SCREEN) и многие другие.
Phaser поддерживает набор режимов, общих для Canvas и WebGL рендерера, а также дополнительные, доступные только для Canvas. Режим DIFFERENCE, который мы рассмотрим, входит в последнюю группу. Он вычитает значение цвета источника из цвета цели или наоборот (берется абсолютное значение), что часто приводит к инверсному, «негативному» эффекту, особенно на контрастных областях.
Разбор примера: структура сцены и загрузка
Код начинается с объявления класса сцены, который наследуется от Phaser.Scene. В конструкторе инициализируется массив this.sprites для хранения данных о наших частицах.
В методе preload загружаются три изображения: фон (bg), текстура частицы (particle) и логотип (logo). Обратите внимание на использование setBaseURL — это удобно, чтобы не писать полный URL для каждого ресурса.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/skies/space1.png');
this.load.image('particle', 'assets/particles/yellow.png');
this.load.image('logo', 'assets/sprites/phaser2.png');
}
Создание частиц с режимом наложения ADD
В методе create сначала отрисовывается фоновое изображение. Затем в цикле создается 300 частиц — обычных изображений (this.add.image), размещенных в случайных позициях за пределами экрана.
Ключевой момент — установка режима наложения для каждой частицы с помощью метода setBlendMode. В примере для частиц используется Phaser.BlendModes.ADD. Этот режим складывает значения RGB источника и цели, делая цвета ярче и создавая эффект светящихся, накладывающихся друг на друга точек. Это классический прием для симуляции свечения, огня или звезд.
Каждая частица и её скорость (хранящаяся в свойстве `r) помещаются в массивthis.sprites` для дальнейшей анимации.
const image = this.add.image(x, y, 'particle');
image.setBlendMode(Phaser.BlendModes.ADD);
this.sprites.push({ s: image, r: 2 + Math.random() * 6 });
Эффект DIFFERENCE для основного объекта
После создания частиц на сцену добавляется логотип Phaser. Для него устанавливается режим наложения Phaser.BlendModes.DIFFERENCE.
Режим DIFFERENCE работает по принципу |фон - лого|. На темном фоне космоса белое лого будет отображаться почти без изменений (разница между черным и белым велика). Однако когда под логотипом пролетают желтые частицы в режиме ADD, их цвет вычитается из цвета логотипа (или наоборот). Поскольку DIFFERENCE берет абсолютное значение разности, это приводит к резкому инвертированию цвета в зоне пересечения: желтая частица под белым лого даст синеватый оттенок. Это создает динамичный, «реактивный» визуальный эффект, где логотип взаимодействует с фоном и движущимися элементами.
this.add.image(400, 300, 'logo').setBlendMode(Phaser.BlendModes.DIFFERENCE);
Анимация: заставляем частицы двигаться
Логика анимации реализована в методе update, который вызывается на каждом кадре. Для каждой частицы из массива this.sprites происходит изменение её координаты `yна величину, равную индивидуальной скорости (r). Когда частица уходит за верхнюю границу экрана (sprite.y < -256`), она телепортируется вниз, создавая бесконечный поток.
update ()
{
for (var i = 0; i < this.sprites.length; i++)
{
const sprite = this.sprites[i].s;
sprite.y -= this.sprites[i].r;
if (sprite.y < -256)
{
sprite.y = 700;
}
}
}
Именно это постоянное движение частиц под логотипом в режиме DIFFERENCE и порождает непрерывно меняющийся цветовой эффект на нем.
Что попробовать дальше
Режимы наложения — это простой, но чрезвычайно эффективный способ добавить вашей игре визуальную изюминку без использования тяжелых шейдеров. Экспериментируйте: попробуйте заменить ADD на SCREEN для более мягкого свечения частиц или примените DIFFERENCE к самим частицам, а лого оставьте в NORMAL. Используйте OVERLAY или HARD_LIGHT для создания текстурных эффектов на UI-элементах. Помните, что для Canvas-специфичных режимов (включая DIFFERENCE) в конфигурации игры должен быть указан type: Phaser.CANVAS.
