О чем этот пример
Визуальные эффекты — мощный инструмент для создания настроения в игре. Они направляют взгляд игрока и подчёркивают важные элементы сцены. В этом примере мы рассмотрим, как добавить динамическую виньетку непосредственно к камере, используя встроенную систему фильтров Phaser. Это простой, но эффективный способ создать ощущение глубины, напряжения или стилизовать картинку, не затрагивая сами игровые объекты. Мы разберём, как применить фильтр к основной камере, анимировать её прокрутку и правильно организовать отрисовку объектов с учётом глубины, чтобы получить красивый параллакс-эффект в пейзаже.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
constructor ()
{
super();
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/textures/grass.jpg');
this.load.atlas('glade', 'assets/atlas/glade.png', 'assets/atlas/glade.json');
}
create ()
{
this.add.image(400, 300, 'bg').setScale(1.0).setScrollFactor(0, 0);
const grass = this.add.layer();
const trees = [ 'Spruce-1', 'Spruce-2', 'Spruce-3', 'Spruce-5', 'Spruce-6', 'Flower_2' ];
for (let i = 0; i < 128; i++)
{
let x = Phaser.Math.Between(0, 800);
let y = Phaser.Math.Between(100, 600 * 4);
let frame = Phaser.Utils.Array.GetRandom(trees);
let tree = this.add.image(x, y, 'glade', frame);
tree.setDepth(y);
tree.setOrigin(0.5, 1);
grass.add(tree);
}
const camera = this.cameras.main;
camera.filters.external.addVignette(0.5, 0.5, 0.7);
this.tweens.add({
targets: camera,
scrollY: 1800,
duration: 20000,
yoyo: true,
loop: -1
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#000000',
parent: 'phaser-example',
scene: Example
};
let game = new Phaser.Game(config);
Подготовка ресурсов и создание слоя
В методе preload загружаются необходимые ассеты: фоновая текстура травы и атлас спрайтов с деревьями и цветами. Обратите внимание, что setBaseURL задаёт базовый путь для всех последующих загрузок.
В create первым делом добавляется фоновое изображение. Ключевой момент — вызов setScrollFactor(0, 0). Это фиксирует фон относительно камеры, создавая иллюзию бесконечного заднего плана.
Затем создаётся слой (this.add.layer()). Слои в Phaser — это удобные контейнеры для управления группой объектов. Мы будем добавлять в него деревья.
this.add.image(400, 300, 'bg').setScale(1.0).setScrollFactor(0, 0);
const grass = this.add.layer();
Генерация леса с параллаксом
Далее в цикле генерируется 128 случайных деревьев. Для каждого дерева выбираются случайные координаты `xиy. Важно, что координатаy` может быть значительно больше высоты экрана (до 2400 пикселей), что позволит камере прокручиваться вверх и вниз.
Ключевой приём для создания иллюзии глубины — установка глубины объекта (setDepth) равной его координате `y. Это стандартный подход для 2.5D или изометрических сцен: чем выше объект на экране (большеy), тем дальше он должен казаться, а значит, должен быть отрисован позади объектов с меньшимy`.
setOrigin(0.5, 1) устанавливает точку привязки спрайта в его нижней середине. Это нужно, чтобы деревья "стояли" на своей координате `y`, а не были привязаны к центру.
После создания объект добавляется в ранее созданный слой grass.
let x = Phaser.Math.Between(0, 800);
let y = Phaser.Math.Between(100, 600 * 4);
let frame = Phaser.Utils.Array.GetRandom(trees);
let tree = this.add.image(x, y, 'glade', frame);
tree.setDepth(y);
tree.setOrigin(0.5, 1);
grass.add(tree);
Добавление фильтра виньетки к камере
Самый важный шаг — применение фильтра. Мы получаем ссылку на основную камеру сцены через this.cameras.main. У камеры есть свойство filters, содержащее коллекцию external. Именно в неё мы можем добавлять готовые визуальные эффекты.
Метод addVignette принимает три параметра: позиция `x, позицияyи сила эффектаradius. Все значения от 0 до 1. В примереaddVignette(0.5, 0.5, 0.7)` создаёт виньетку, центрированную по камере, с довольно сильным затемнением по краям. Этот эффект применяется ко всему, что видит камера, включая фон и все объекты на слое.
const camera = this.cameras.main;
camera.filters.external.addVignette(0.5, 0.5, 0.7);
Анимация прокрутки камеры
Чтобы продемонстрировать динамичность эффекта, камера приводится в движение. Создаётся твин, который анимирует свойство scrollY камеры от начального значения до 1800 пикселей за 20 секунд.
Параметры yoyo: true и loop: -1 заставляют анимацию проигрываться в прямом и обратном направлении бесконечно. Это создаёт плавную "прогулку" камеры по лесу, а виньетка, оставаясь закреплённой на камере, равномерно затемняет края изображения на всём протяжении движения.
this.tweens.add({
targets: camera,
scrollY: 1800,
duration: 20000,
yoyo: true,
loop: -1
});
Что попробовать дальше
Мы реализовали атмосферную сцену с параллаксом и стилизующим фильтром. Ключевые выводы: фильтры камеры (camera.filters.external) влияют на весь её вид; установка scrollFactor и depth позволяет легко управлять перспективой; встроенные методы вроде addVignette дают быстрый визуальный результат.
Для экспериментов попробуйте: изменить параметры виньетки (например, сместить центр `xв 0.2 для асимметрии); добавить другие фильтры изexternal(например,addGlowилиaddShadow); анимировать неscrollY`, а сами параметры фильтра через твин, чтобы виньетка пульсировала или смещалась.
