О чем этот пример
Визуальные эффекты — мощный инструмент для создания атмосферы в игре. Фильтры спрайтов в Phaser позволяют применять к изображениям сложные преобразования в реальном времени без создания дополнительных текстур. В этой статье мы разберем, как использовать встроенный фильтр `Barrel` для создания эффекта "рыбьего глаза" или, наоборот, вогнутого искажения. Этот прием может оживить магические сферы, кривые зеркала, линзы бинокля или просто добавить психоделический оттенок вашей графике.
Версия 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('block', 'assets/pics/lance-overdose-loader-eye.png');
}
create ()
{
let amount = 0.5;
for (let y = 0; y < 2; y++)
{
for (let x = 0; x < 3; x++)
{
const sprite = this.add.sprite(128 + x * 256, 128 + y * 256, 'block');
sprite.enableFilters();
// Enlarge filter view.
sprite.focusFiltersOverride(undefined, undefined, sprite.width + 64, sprite.height + 64);
sprite.filters.internal.addBarrel(amount);
this.add.text(128 + x * 256, 128 + y * 256 + 96, amount).setOrigin(0.5, 0).setResolution(window.devicePixelRatio);
amount += 0.25;
}
}
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#47255b',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и загрузка ресурсов
Как и в большинстве примеров Phaser, работа начинается в методе preload сцены. Здесь мы загружаем одно изображение, которое впоследствии будем искажать.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('block', 'assets/pics/lance-overdose-loader-eye.png');
}
Метод setBaseURL устанавливает базовый URL для всех последующих загрузок, что удобно, если все ресурсы хранятся в одном месте. Ключ 'block' — это внутреннее имя загруженного изображения, которое мы будем использовать для создания спрайтов.
Создание спрайтов и активация фильтров
В методе create мы размещаем несколько спрайтов на сцене в виде сетки 3x2. Каждому из них будет применен фильтр с разной силой эффекта.
let amount = 0.5;
for (let y = 0; y < 2; y++)
{
for (let x = 0; x < 3; x++)
{
const sprite = this.add.sprite(128 + x * 256, 128 + y * 256, 'block');
sprite.enableFilters();
Циклы создают 6 спрайтов, позиционируя их с шагом в 256 пикселей. Ключевой метод sprite.enableFilters() активирует систему фильтров для данного конкретного спрайта. Без этого вызова любые попытки добавить фильтр будут игнорироваться.
Настройка области фильтра и добавление эффекта
По умолчанию фильтр применяется только к области самого спрайта. Эффект "бочки" может искажать края за эти пределы, поэтому важно расширить область видимости фильтра.
sprite.focusFiltersOverride(undefined, undefined, sprite.width + 64, sprite.height + 64);
sprite.filters.internal.addBarrel(amount);
Метод focusFiltersOverride позволяет переопределить область, которую "видит" фильтр. Первые два аргумента undefined оставляют смещение (`x,y`) по умолчанию (центр спрайта). Третий и четвертый аргументы задают ширину и высоту новой области, увеличенные на 64 пикселя с каждой стороны. Это гарантирует, что искаженные края изображения не будут обрезаны.
Затем мы обращаемся к внутреннему менеджеру фильтров спрайта (sprite.filters.internal) и вызываем метод addBarrel(amount). Параметр amount управляет силой и типом искажения:
* Положительные значения создают выпуклый эффект (как "рыбий глаз").
* Отрицательные значения создают вогнутый эффект.
* Значение `0` не дает искажения.
В нашем примере amount начинается с 0.5 и увеличивается на 0.25 для каждого следующего спрайта, что позволяет наглядно сравнить результат.
Визуализация параметров и конфигурация игры
Чтобы было понятно, какое значение amount соответствует каждому спрайту, под ним создается текстовый объект.
this.add.text(128 + x * 256, 128 + y * 256 + 96, amount).setOrigin(0.5, 0).setResolution(window.devicePixelRatio);
Метод setOrigin(0.5, 0) устанавливает точку привязки текста по горизонтали в центр, а по вертикали — в верхний край. Это центрирует текст под спрайтом. setResolution помогает правильно отображать текст на экранах с высоким DPI.
Финальная часть кода — стандартная конфигурация экземпляра игры Phaser.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#47255b',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Здесь задается разрешение холста, фоновый цвет (backgroundColor), идентификатор HTML-контейнера (parent) и главная сцена.
Что попробовать дальше
Фильтр Barrel — это простой, но эффективный способ добавить динамические оптические искажения в вашу игру. Он работает непосредственно на GPU, поэтому производительность остается высокой даже при множестве обработанных спрайтов. Для экспериментов попробуйте:
1. Менять параметр amount в реальном времени в ответ на действия игрока (например, при активации "увеличения").
2. Комбинировать addBarrel с другими фильтрами из sprite.filters.internal, такими как addGlow или addBloom.
3. Применять фильтр не ко всему спрайту, а только к его части, манипулируя параметрами focusFiltersOverride.
