О чем этот пример
Эффекты освещения могут преобразить вашу игру, добавив атмосферности и глубины. В Phaser 3 система освещения позволяет легко создавать динамические световые сцены. В этой статье мы разберем практический пример, где источник света привязан к движению указателя мыши, а также добавлены статические и анимированные огни. Вы узнаете, как включать освещение для спрайтов, управлять его параметрами и создавать простые, но впечатляющие визуальные эффекты.
Версия 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('brick', [ 'assets/normal-maps/brick.jpg', 'assets/normal-maps/brick_n.png' ]);
this.load.image('phaser', 'assets/sprites/phaser2.png');
}
create ()
{
const brick = this.add.sprite(0, 0, 'brick');
brick.setOrigin(0, 0);
brick.setLighting(true);
this.light = this.lights.addLight(0, 0, 200).setScrollFactor(0).setIntensity(2);
this.lights.enable().setAmbientColor(0x555555);
this.input.on('pointermove', pointer =>
{
this.light.x = pointer.x;
this.light.y = pointer.y;
});
this.input.on('pointerdown', pointer =>
{
if (this.lights.active)
{
this.lights.disable();
}
else
{
this.lights.enable();
}
});
this.add.image(300, 400, 'phaser').setLighting(true);
this.lights.addLight(0, 100, 100).setColor(0xff0000).setIntensity(3.0);
this.lights.addLight(0, 200, 100).setColor(0x00ff00).setIntensity(3.0);
this.lights.addLight(0, 300, 100).setColor(0x0000ff).setIntensity(3.0);
this.lights.addLight(0, 400, 100).setColor(0xffff00).setIntensity(3.0);
this.offsets = [ Math.random() + 1 - 2, Math.random() + 1 - 2, Math.random() + 1 - 2, Math.random() + 1 - 2 ];
this.time = 0;
}
update ()
{
let index = 0;
this.lights.lights.forEach(currLight =>
{
if (this.light !== currLight)
{
currLight.x = 400 + Math.sin(this.offsets[index]) * 1000;
this.offsets[index] += 0.02;
index += 1;
}
});
this.cameras.main.scrollX = Math.sin(this.time) * 400;
this.time += 0.01;
}
}
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и загрузка ассетов
В методе preload мы загружаем два изображения. Обратите внимание на загрузку текстуры кирпича: первым аргументом передается обычная текстура, а вторым — ее карта нормалей. Карта нормалей необходима для корректного расчета освещения, чтобы свет "обтекал" неровности поверхности, создавая эффект объема.
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('brick', [ 'assets/normal-maps/brick.jpg', 'assets/normal-maps/brick_n.png' ]);
this.load.image('phaser', 'assets/sprites/phaser2.png');
Создание основного света и его привязка к курсору
В методе create мы создаем фон из спрайта кирпича и активируем для него систему освещения с помощью метода setLighting(true). Без этого вызова свет на спрайте не будет отображаться.
Затем создается главный источник света с помощью this.lights.addLight(0, 0, 200). Первые два аргумента — это начальные координаты X и Y, третий — радиус света. Метод setScrollFactor(0) фиксирует свет относительно камеры (он не будет двигаться при скролле), а setIntensity(2) задает его интенсивность.
Ключевой момент — привязка координат света к положению указателя мыши. Для этого мы подписываемся на событие pointermove.
const brick = this.add.sprite(0, 0, 'brick');
brick.setOrigin(0, 0);
brick.setLighting(true);
this.light = this.lights.addLight(0, 0, 200).setScrollFactor(0).setIntensity(2);
this.lights.enable().setAmbientColor(0x555555);
this.input.on('pointermove', pointer => {
this.light.x = pointer.x;
this.light.y = pointer.y;
});
Управление системой освещения и добавление статических огней
В примере реализовано простое переключение всей системы освещения по клику мыши. При событии pointerdown проверяется состояние this.lights.active, и система либо отключается (disable()), либо включается (enable()).
Далее мы добавляем спрайт логотипа Phaser, который также будет реагировать на свет, и создаем четыре стационарных источника света разного цвета с высокой интенсивностью. Цвет задается методом setColor() в шестнадцатеричном формате.
this.input.on('pointerdown', pointer => {
if (this.lights.active)
{
this.lights.disable();
}
else
{
this.lights.enable();
}
});
this.add.image(300, 400, 'phaser').setLighting(true);
this.lights.addLight(0, 100, 100).setColor(0xff0000).setIntensity(3.0);
this.lights.addLight(0, 200, 100).setColor(0x00ff00).setIntensity(3.0);
this.lights.addLight(0, 300, 100).setColor(0x0000ff).setIntensity(3.0);
this.lights.addLight(0, 400, 100).setColor(0xffff00).setIntensity(3.0);
Анимация и движение в игровом цикле
В методе update происходит вся анимация. Мы проходим по всем созданным источникам света в массиве this.lights.lights, кроме главного (привязанного к курсору). Для каждого из четырех цветных огней мы меняем координату X по синусоидальному закону, используя заранее сгенерированные случайные смещения (offsets). Это создает эффект плавающего, хаотичного движения огоньков.
Отдельно анимируется скроллинг основной камеры по оси X, также с помощью синуса. Это демонстрирует, как свет, созданный с setScrollFactor(0), остается на месте, в то время как мир с текстурами и другими огнями движется.
update ()
{
let index = 0;
this.lights.lights.forEach(currLight =>
{
if (this.light !== currLight)
{
currLight.x = 400 + Math.sin(this.offsets[index]) * 1000;
this.offsets[index] += 0.02;
index += 1;
}
});
this.cameras.main.scrollX = Math.sin(this.time) * 400;
this.time += 0.01;
}
Важные настройки конфигурации
Для работы системы освещения в Phaser 3 критически важно указать правильный тип рендерера. Освещение работает только в контексте WebGL. Это задается в объекте конфигурации игры полем type: Phaser.WEBGL. Если указать Phaser.CANVAS, освещение не будет функционировать.
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Система освещения Phaser 3 предоставляет мощный, но относительно простой инструмент для добавления динамических световых эффектов. Из этого примера вы освоили ключевые концепции: активацию освещения для объектов, создание и настройку источников света, их привязку к событиям ввода и анимацию. Для экспериментов попробуйте изменить параметры света (радиус, интенсивность, цвет), заменить карту нормалей на своей текстуре или привязать свет не к курсору, а к движению игрового персонажа.
