О чем этот пример
Освещение — мощный инструмент для создания атмосферы и глубины в 2D-играх. Phaser 3 предоставляет встроенную систему освещения, которая работает в связке с нормальными картами, позволяя имитировать динамические световые эффекты. Эта статья разбирает практический пример, где точечный свет вращается вокруг анимированного спрайта-паука, создавая эффект прожектора в темноте. Вы научитесь настраивать источники света, привязывать их к геометрии и анимировать, что пригодится для создания уровней в подземельях, исследований с фонариком или просто для добавления визуального шарма вашим сценам.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
point;
circle;
light;
guide;
spider;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('spider', [ 'assets/normal-maps/spider.png', 'assets/normal-maps/spider_n.png' ]);
this.load.image('light', 'assets/normal-maps/light.png');
}
create ()
{
this.spider = this.add.sprite(400, 300, 'spider');
this.spider.setLighting(true);
this.light = this.lights.addLight(0, 0, 500).setIntensity(6);
this.lights.enable().setAmbientColor(0x888888);
// So you can see where the light is positioned
this.circle = new Phaser.Geom.Circle(400, 300, 200);
this.guide = this.add.image(0, 0, 'light');
}
update ()
{
this.spider.rotation += 0.005;
Phaser.Geom.Circle.CircumferencePoint(this.circle, this.spider.rotation - (Math.PI / 2), this.guide);
this.light.x = this.guide.x;
this.light.y = this.guide.y;
}
}
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Настройка сцены и загрузка ассетов
Класс Example расширяет Phaser.Scene. В методе preload загружаются два ключевых изображения.
this.load.image('spider', [ 'assets/normal-maps/spider.png', 'assets/normal-maps/spider_n.png' ]);
this.load.image('light', 'assets/normal-maps/light.png');
Обратите внимание на массив для ключа 'spider'. Первый элемент — это обычная диффузная текстура, а второй (spider_n.png) — нормальная карта (normal map). Нормальная карта кодирует информацию о поверхности объекта (выступы, впадины), что необходимо для корректной работы системы освещения. Изображение 'light' — это спрайт-маркер, который будет визуально показывать позицию источника света в игре.
Создание объектов и включение освещения
В методе create происходит основная инициализация. Сначала создается спрайт паука и активируется для него расчет освещения с помощью метода setLighting(true).
this.spider = this.add.sprite(400, 300, 'spider');
this.spider.setLighting(true);
Затем создается точечный источник света. Метод this.lights.addLight(x, y, radius) добавляет свет с заданными координатами и радиусом влияния. Интенсивность света повышается до 6.
this.light = this.lights.addLight(0, 0, 500).setIntensity(6);
Чтобы система освещения начала работать, ее нужно явно включить. Также устанавливается фоновый (ambient) свет. Без него неосвещенные области были бы абсолютно черными.
this.lights.enable().setAmbientColor(0x888888);
После этого создается геометрическая окружность (Phaser.Geom.Circle) и маркер (this.guide). Окружность задает траекторию движения света, а маркер — его визуальное представление на экране.
Анимация и привязка света к траектории
В методе update происходят вычисления каждый кадр. Спрайт паука медленно вращается.
this.spider.rotation += 0.005;
Ключевой момент — вычисление точки на окружности. Статический метод Phaser.Geom.Circle.CircumferencePoint принимает окружность, угол и объект, в свойства `xиyкоторого будет записан результат. Угол берется от вращения паука, со смещением на-Math.PI/2`, чтобы свет изначально был сверху.
Phaser.Geom.Circle.CircumferencePoint(this.circle, this.spider.rotation - (Math.PI / 2), this.guide);
Полученные координаты маркера this.guide сразу же присваиваются источнику света. Таким образом, свет жестко привязан к визуальному маркеру и движется по круговой траектории вслед за вращением паука.
this.light.x = this.guide.x;
this.light.y = this.guide.y;
Конфигурация игры и запуск
Важное условие для работы освещения — использование рендерера WEBGL. В конфигурации игры type должен быть установлен в Phaser.WEBGL, так как система освещения не работает с рендерером CANVAS.
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
После создания экземпляра Phaser.Game с этой конфигурацией сцена начнет свою работу, и вы увидите анимированного паука под вращающимся лучом света.
Что попробовать дальше
Вы разобрали рабочую схему динамического освещения в Phaser 3. Связка нормальных карт, источников света и геометрии открывает большие возможности. Для экспериментов попробуйте: изменить форму траектории с круга на эллипс или путь по точкам (Phaser.Curves.Path), добавить несколько независимых источников света, которые будут реагировать на движение игрока, или изменять цвет (setColor) и интенсивность света в реальном времени для создания эффекта мерцания или вспышек.
