О чем этот пример
Световые эффекты — мощный инструмент для создания атмосферы и глубины в 2D-играх. В Phaser 3 система освещения позволяет оживлять статичные сцены, делая их интерактивными и визуально привлекательными. В этой статье мы разберём практический пример, где динамический источник света взаимодействует с bitmap-текстом и спрайтами, реагируя на движения и клики мыши. Вы научитесь подключать и настраивать освещение для нестандартных объектов, что откроет новые возможности для визуального оформления ваших проектов.
Версия 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('sonic', 'assets/sprites/sonic_havok_sanity.png');
this.load.image('bg', [ 'assets/textures/gold.png', 'assets/textures/gold-n.png' ]);
this.load.bitmapFont('ice', [ 'assets/fonts/bitmap/iceicebaby.png', 'assets/fonts/bitmap/iceicebaby_n.png' ], 'assets/fonts/bitmap/iceicebaby.xml');
}
create ()
{
this.add.sprite(400, 300, 'bg')
.setLighting(true)
.setAlpha(0.2);
this.add.sprite(680, 600, 'sonic').setOrigin(0.5, 1);
this.add.bitmapText(400, 300, 'ice', 'Bitmap Text\nwith Lights', 110)
.setCenterAlign()
.setOrigin(0.5)
.setLighting(true);
this.lights.enable();
this.lights.setAmbientColor(0x808080);
const spotlight = this.lights.addLight(400, 300, 280).setIntensity(3);
this.input.on('pointermove', pointer =>
{
spotlight.x = pointer.x;
spotlight.y = pointer.y;
});
const colors = [
0xffffff, 0xff0000, 0x00ff00, 0x00ffff, 0xff00ff, 0xffff00
];
let currentColor = 0;
this.input.on('pointerdown', pointer =>
{
currentColor++;
if (currentColor === colors.length)
{
currentColor = 0;
}
spotlight.setColor(colors[currentColor]);
});
}
}
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Подготовка ассетов с нормалями
Для работы системы динамического освещения в WebGL-рендерере Phaser необходимы не только обычные текстуры, но и карты нормалей (normal maps). Нормаль определяет, как поверхность объекта взаимодействует со светом, создавая иллюзию объёма.
В методе preload мы загружаем три типа ассетов, обращая внимание на особенности загрузки для освещения:
this.load.image('sonic', 'assets/sprites/sonic_havok_sanity.png');
this.load.image('bg', [ 'assets/textures/gold.png', 'assets/textures/gold-n.png' ]);
this.load.bitmapFont('ice', [ 'assets/fonts/bitmap/iceicebaby.png', 'assets/fonts/bitmap/iceicebaby_n.png' ], 'assets/fonts/bitmap/iceicebaby.xml');
Ключевой момент — передача массивов путей для текстур 'bg' и шрифта 'ice'. Первый элемент массива — это путь к диффузной текстуре (основному цвету), а второй — путь к карте нормалей (суффикс -n). Phaser автоматически связывает эти текстуры для корректного расчёта освещения. Обычный спрайт 'sonic' загружается без нормалей, поэтому на него свет будет падать без учёта рельефа поверхности.
Создание сцены и включение освещения
В методе create мы сначала размещаем фоновый спрайт и персонажа, а затем создаём bitmap-текст. Обратите внимание на цепочки методов для настройки.
this.add.sprite(400, 300, 'bg').setLighting(true).setAlpha(0.2);
this.add.bitmapText(400, 300, 'ice', 'Bitmap Text\nwith Lights', 110).setCenterAlign().setOrigin(0.5).setLighting(true);
Метод setLighting(true) — это самый важный вызов. Он указывает рендереру, что данный игровой объект должен реагировать на динамические источники света в сцене. Без этого вызова объект будет отрисован с использованием только окружающего света.
Далее мы активируем саму систему освещения для сцены:
this.lights.enable();
this.lights.setAmbientColor(0x808080);
this.lights.enable() включает систему. this.lights.setAmbientColor(0x808080) устанавливает цвет окружающего освещения — в данном случае средний серый (0x808080). Это базовый свет, который равномерно освещает все объекты с включённым lighting, независимо от расположения источников.
Создание и управление динамическим источником света
После включения системы мы создаём основной источник света — прожектор (spotlight).
const spotlight = this.lights.addLight(400, 300, 280).setIntensity(3);
this.lights.addLight(x, y, radius) создаёт точечный источник света с заданными координатами и радиусом влияния (280 пикселей). Метод setIntensity(3) устанавливает интенсивность. Значение больше 1 делает свет ярче стандартного.
Затем мы привязываем этот источник к курсору мыши, обрабатывая события pointermove:
this.input.on('pointermove', pointer => {
spotlight.x = pointer.x;
spotlight.y = pointer.y;
});
При каждом движении мыши мы просто обновляем координаты `xиyобъектаspotlight`. Phaser автоматически пересчитывает освещение сцены в следующем кадре, создавая плавный эффект следования света за курсором.
Интерактивная смена цвета света
Чтобы сделать пример более наглядным и интерактивным, добавим возможность менять цвет прожектора по клику мыши. Для этого определим массив цветов в формате HEX.
const colors = [
0xffffff, 0xff0000, 0x00ff00, 0x00ffff, 0xff00ff, 0xffff00
];
Затем в обработчике события pointerdown мы циклически перебираем этот массив и применяем цвет к источнику света.
this.input.on('pointerdown', pointer => {
currentColor++;
if (currentColor === colors.length) {
currentColor = 0;
}
spotlight.setColor(colors[currentColor]);
});
Метод setColor() объекта света мгновенно изменяет его оттенок. Это отличный способ визуальной обратной связи или создания спецэффектов (например, мигания сигнальных огней или изменения настроения сцены).
Конфигурация игры: важность WebGL
Система динамического освещения в Phaser 3 работает исключительно в контексте WebGL. Это важно указать в конфигурационном объекте игры.
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
Если установить type: Phaser.CANVAS, то освещение работать не будет. WebGL-рендерер использует шейдеры для расчёта взаимодействия света, нормалей и диффузных текстур, что позволяет добиться плавной производительности даже при нескольких движущихся источниках света.
Что попробовать дальше
Система освещения Phaser 3 — это гибкий инструмент, который превращает плоскую 2D-графику в нечто объёмное и живое. В этом примере мы увидели, как легко заставить свет следовать за курсором и менять цвет по клику, взаимодействуя с bitmap-текстом и текстурой с нормалями. Для экспериментов попробуйте: добавить несколько источников света с разными радиусами и интенсивностью, привязать их к движущимся спрайтам (например, к факелу в руке персонажа), создать эффект мерцания с помощью таймера или использовать освещение для подсветки только определённых зон игры, создавая атмосферу тайны.
