О чем этот пример
Освещение — это мощный инструмент для создания атмосферы и глубины в 2D-играх. Phaser 3 предоставляет удобную систему точечных источников света (Point Lights), которые можно динамически изменять во время выполнения. В этой статье мы разберем практический пример, показывающий, как создавать источник света, управлять его цветом, радиусом и затуханием, а также перемещать его с помощью мыши и клавиатуры. Этот подход позволит вам легко добавить динамическое освещение в свои игры, будь то фонарик у персонажа, свет от магического шара или костра.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
constructor ()
{
super();
}
create ()
{
this.add.text(10, 10, 'Wheel: Hue\nA + D: Radius\nW + S: Attenuation\nClick to set Light').setDepth(1);
let colorIndex = 0;
const spectrum = Phaser.Display.Color.ColorSpectrum(128);
let radius = 128;
let intensity = 1;
let attenuation = 0.1;
let light = this.add.pointlight(400, 300, 0, radius, intensity);
let color = spectrum[colorIndex];
light.color.setTo(color.r, color.g, color.b);
colorIndex++;
this.input.on('pointerdown', pointer => {
light = this.add.pointlight(pointer.x, pointer.y, 0, radius, intensity);
light.attenuation = attenuation;
light.color.setTo(color.r, color.g, color.b);
});
this.input.on('pointermove', pointer => {
light.x = pointer.x;
light.y = pointer.y;
});
this.input.on('wheel', (pointer, over, deltaX, deltaY, deltaZ) => {
if (deltaY < 0)
{
colorIndex--;
}
else if (deltaY > 0)
{
colorIndex++;
}
if (colorIndex === spectrum.length)
{
colorIndex = 0;
}
else if (colorIndex < 0)
{
colorIndex = spectrum.length - 1;
}
color = spectrum[colorIndex];
light.color.setTo(color.r, color.g, color.b);
});
this.input.keyboard.on('keydown-A', () => {
light.radius--;
radius--;
});
this.input.keyboard.on('keydown-D', () => {
light.radius++;
radius++;
});
this.input.keyboard.on('keydown-W', () => {
light.attenuation += 0.01;
attenuation += 0.01;
});
this.input.keyboard.on('keydown-S', () => {
light.attenuation -= 0.01;
attenuation -= 0.01;
});
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#000000',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Инициализация сцены и создание света
В методе create() сцены мы создаем текстовую подсказку и подготавливаем все необходимые переменные. Ключевой объект — light, создаваемый с помощью метода this.add.pointlight(). Он добавляется на сцену как игровой объект.
let radius = 128;
let intensity = 1;
let attenuation = 0.1;
let light = this.add.pointlight(400, 300, 0, radius, intensity);
Метод add.pointlight() принимает следующие аргументы: координаты X и Y, цвет (изначально 0), радиус и интенсивность. Цвет мы зададим отдельно. Также мы создаем массив цветов spectrum с помощью утилиты Phaser.Display.Color.ColorSpectrum(128), который содержит 128 цветов плавного спектра. Это удобно для циклического перебора оттенков.
Управление цветом и перемещение света
Цвет света задается через свойство light.color, которое является объектом типа Color. Мы используем метод setTo() для установки RGB-значений из текущего цвета в массиве spectrum.
light.color.setTo(color.r, color.g, color.b);
Перемещение света реализовано через обработчик события pointermove. Мы просто обновляем координаты `xиyобъектаlight`. Это позволяет перетаскивать источник света по сцене мышью.
this.input.on('pointermove', pointer => {
light.x = pointer.x;
light.y = pointer.y;
});
Смена цвета происходит при прокрутке колесика мыши (wheel). В зависимости от направления прокрутки (deltaY) мы увеличиваем или уменьшаем индекс colorIndex и выбираем новый цвет из spectrum, после чего применяем его к свету.
Динамическое изменение радиуса и затухания
Радиус света — это расстояние, на которое распространяется его свечение. Им можно управлять через свойство light.radius. В примере радиус увеличивается и уменьшается при нажатии клавиш 'D' и 'A' соответственно.
this.input.keyboard.on('keydown-D', () => {
light.radius++;
radius++;
});
Затухание (attenuation) определяет, как быстро свет ослабевает от центра к краям. Чем больше значение, тем резче падает интенсивность. Затухание меняется клавишами 'W' и 'S'. Важно: значение attenuation нужно задавать явно при создании нового света (по клику), так как это свойство не копируется из переменной по умолчанию.
light.attenuation = attenuation;
Создание новых источников по клику
По клику мыши создается новый точечный источник света в месте нажатия. Это демонстрирует, как можно динамически добавлять объекты освещения в игре — например, при касте заклинания или размещении факела.
this.input.on('pointerdown', pointer => {
light = this.add.pointlight(pointer.x, pointer.y, 0, radius, intensity);
light.attenuation = attenuation;
light.color.setTo(color.r, color.g, color.b);
});
Обратите внимание: переменная light перезаписывается, и все последующие обработчики событий (движение, изменение радиуса) будут работать уже с новым источником. Если вам нужно управлять несколькими источниками одновременно, потребуется хранить их в массиве и обрабатывать все объекты в цикле.
Что попробовать дальше
Точечные источники света в Phaser 3 — это гибкий инструмент для создания динамического освещения. Вы научились создавать свет, менять его параметры в реальном времени и реагировать на действия игрока. Для экспериментов попробуйте привязать источник света к спрайту персонажа, создавая эффект фонарика. Или используйте массив источников для освещения нескольких объектов, меняя их цвет в зависимости от игровых событий (например, сигнализация). Поэкспериментируйте с комбинацией света и частиц (particle emitter) для создания магических эффектов.
