О чем этот пример
Визуальные эффекты — мощный инструмент для создания атмосферы в играх. Фильтр Pixelate (пикселизация) позволяет мгновенно придать графике стиль ретро, создать эффект помех, сбоя матрицы или просто интересный переход. Этот встроенный в Phaser фильтр работает на GPU, что делает его производительным и простым в применении к любому игровому объекту. В этой статье мы разберем готовый пример из официальной коллекции 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('phaserlogo', 'assets/sprites/phaser2.png');
}
create ()
{
const phaserLogoImg = this.add.image(this.scale.width / 2, this.scale.height / 2 - 50, 'phaserlogo');
const fxPixelated = phaserLogoImg.enableFilters().filters.internal.addPixelate(-1);
// Text to show the current build target
const shape = this.add.rectangle(this.sys.scale.width / 2, this.sys.scale.height / 2 + 160, this.sys.scale.width, 30, 0x000000, 0.8);
const textDebug = this.add.text(this.sys.scale.width / 2, this.sys.scale.height / 2 + 160, `Pixel Amount:-1.00`, {fontSize: 25}).setOrigin(.5);
// Loop to change the pixel amount
this.time.addEvent({
delay: 1000,
callback: () => {
this.tweens.addCounter({
from: -1,
to: 10,
duration: 2000,
yoyo: true,
repeat: -1,
onUpdate: (value) => {
fxPixelated.amount = value.getValue();
textDebug.setText(`Pixel Amount:${fxPixelated.amount.toFixed(2).padStart(5, " ")}`);
}
})
}
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
pixelArt: true,
backgroundColor: '#000022',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и загрузка ассетов
Всё начинается в методе preload(). Здесь мы указываем базовый URL для загрузки ресурсов и загружаем одно изображение — логотип Phaser, которое будем обрабатывать.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('phaserlogo', 'assets/sprites/phaser2.png');
}
Метод setBaseURL задаёт корневую папку для всех последующих загрузок, что удобно, если все ресурсы хранятся в одном месте. Ключ 'phaserlogo' — это внутреннее имя текстуры, по которому мы будем обращаться к изображению позже.
Создание объекта и добавление фильтра
В методе create() происходит основная магия. Сначала мы создаём изображение и центрируем его на экране с небольшим смещением по вертикали.
const phaserLogoImg = this.add.image(this.scale.width / 2, this.scale.height / 2 - 50, 'phaserlogo');
Затем мы включаем систему фильтров для этого конкретного объекта и добавляем к ней фильтр Pixelate. Цепочка вызовов выглядит так:
const fxPixelated = phaserLogoImg.enableFilters().filters.internal.addPixelate(-1);
Метод enableFilters() активирует конвейер фильтров для спрайта phaserLogoImg. Свойство filters.internal предоставляет доступ к внутреннему менеджеру фильтров этого объекта. Метод addPixelate(-1) создаёт и добавляет сам фильтр пикселизации, где аргумент -1 — начальное значение силы эффекта (amount). Важно сохранить возвращаемую ссылку fxPixelated — через неё мы будем управлять фильтром.
Интерфейс для отладки: текст и фон
Чтобы визуально отслеживать изменение параметра фильтра, пример создаёт простой UI. Сначала рисуется полупрозрачная черная панель с помощью add.rectangle.
const shape = this.add.rectangle(this.sys.scale.width / 2, this.sys.scale.height / 2 + 160, this.sys.scale.width, 30, 0x000000, 0.8);
Затем поверх неё создаётся текстовый объект, который будет отображать текущее значение.
const textDebug = this.add.text(this.sys.scale.width / 2, this.sys.scale.height / 2 + 160, `Pixel Amount:-1.00`, {fontSize: 25}).setOrigin(.5);
Метод setOrigin(.5) центрирует текст относительно его позиции, что упрощает выравнивание. Изначальный текст показывает стартовое значение amount равное -1.
Анимация параметра фильтра с помощью твинов
Самая динамичная часть примера — это цикл, который плавно меняет силу пикселизации от -1 до 10 и обратно. Используется встроенный менеджер времени и система твинов Phaser.
this.time.addEvent({
delay: 1000,
callback: () => {
this.tweens.addCounter({
from: -1,
to: 10,
duration: 2000,
yoyo: true,
repeat: -1,
onUpdate: (value) => {
fxPixelated.amount = value.getValue();
textDebug.setText(`Pixel Amount:${fxPixelated.amount.toFixed(2).padStart(5, " ")}`);
}
})
}
});
time.addEvent с delay: 1000 запускает колбэк через секунду после старта сцены. Внутри создаётся твин для счётчика (addCounter). Параметры from и to задают диапазон значений. yoyo: true заставляет анимацию проигрываться в обратном порядке, а repeat: -1 делает цикл бесконечным.
В колбэке onUpdate мы получаем текущее значение твина через value.getValue() и присваиваем его свойству fxPixelated.amount. Это непосредственно меняет степень пикселизации на спрайте. Одновременно обновляется текст для отладки с форматированием до двух знаков после запятой.
Конфигурация игры: важная настройка pixelArt
Для корректного отображения пиксельной графики и фильтров в конфиге игры включён ключевой параметр.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
pixelArt: true,
backgroundColor: '#000022',
parent: 'phaser-example',
scene: Example
};
Установка pixelArt: true отключает линейную интерполяцию текстур при масштабировании. Это критически важно, если вы работаете с пиксель-артом, чтобы сохранить чёткие границы пикселей. Также здесь задаётся тёмно-синий фон (backgroundColor), на котором хорошо видно логотип, и указывается родительский HTML-элемент (parent) для канваса.
Что попробовать дальше
Фильтр Pixelate в Phaser 3 — это простой, но эффективный способ добавить динамические визуальные искажения. Как показал пример, для его использования достаточно нескольких строк кода: включить фильтры для объекта, добавить эффект и управлять его свойством amount. Система твинов позволяет легко анимировать это свойство, создавая плавные переходы.
Идеи для экспериментов: попробуйте применить фильтр не к статичному спрайту, а к анимированному персонажу. Свяжите значение amount со здоровьем игрока — чем оно меньше, тем сильнее пикселизация, создавая эффект ранения. Или используйте резкое изменение параметра для визуализации телепортации или сбоя в цифровом мире. Фильтр также можно комбинировать с другими, например, с Grayscale или Blur, для создания сложных составных эффектов.
