О чем этот пример
Работа с цветом и освещением — ключ к атмосферным 2D-играм. В Phaser 3 методы `.setTint()` и `.setTintFill()` влияют на объекты по-разному, особенно при использовании системы света Light2D. Этот пример наглядно демонстрирует разницу, которая часто становится источником визуальных багов, если её не понимать. Знание этой механики позволит вам точно контролировать внешний вид спрайтов под динамическим освещением, создавая более глубокие и живые сцены.
Версия 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('mushroom', 'assets/particles/glass.png');
}
create ()
{
this.add.image(200, 300, 'mushroom').setPipeline("Light2D");
this.add.image(400, 300, 'mushroom').setTint(0xff00ff).setPipeline("Light2D");
this.add.image(600, 300, 'mushroom').setTintFill(0xff00ff).setPipeline("Light2D");
this.lights.enable()
this.lights.setAmbientColor("#0x999999")
this.lights.addLight(200, 300, 1000, undefined, 2)
this.lights.addLight(400, 300, 1000, undefined, 2)
this.lights.addLight(600, 300, 1000, undefined, 2)
}
}
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#000000',
scene: [ Example ]
};
const game = new Phaser.Game(config);
Подготовка сцены и загрузка ассетов
В методе preload мы загружаем одно текстуру — изображение частицы стекла. Важно использовать WEBGL-рендеринг, так как конвейер Light2D работает только с ним.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('mushroom', 'assets/particles/glass.png');
}
Создание объектов с разными типами тонирования
В create мы добавляем три одинаковых спрайта на разных позициях по X. Каждый из них подключен к конвейеру "Light2D" с помощью .setPipeline(). Без этого шага освещение на них не повлияет.
Первый спрайт добавлен без тонирования, как эталон.
Второй спрайт тонирован стандартным методом .setTint(0xff00ff).
Третий спрайт тонирован методом .setTintFill(0xff00ff).
this.add.image(200, 300, 'mushroom').setPipeline("Light2D");
this.add.image(400, 300, 'mushroom').setTint(0xff00ff).setPipeline("Light2D");
this.add.image(600, 300, 'mushroom').setTintFill(0xff00ff).setPipeline("Light2D");
Настройка системы освещения
Перед добавлением источников света систему необходимо активировать и задать фоновый (ambient) цвет. this.lights.enable() включает Light2D для текущей сцены. this.lights.setAmbientColor("#0x999999") устанавливает фоновый серый свет, который смешивается со светом от источников.
this.lights.enable()
this.lights.setAmbientColor("#0x999999")
Добавление источников света
Над каждым спрайтом размещается свой источник света с помощью this.lights.addLight(). Параметры: позиция X, Y, радиус (1000 пикселей), цвет (undefined, значит белый) и интенсивность (2). Большой радиус гарантирует, что свет от каждого источника будет покрывать всю сцену, создавая три ярких перекрывающихся пятна.
this.lights.addLight(200, 300, 1000, undefined, 2)
this.lights.addLight(400, 300, 1000, undefined, 2)
this.lights.addLight(600, 300, 1000, undefined, 2)
В чём разница между Tint и TintFill?
Именно здесь проявляется ключевое отличие, которое показывает пример:
* **.setTint()** — это **аддитивное** тонирование. Цвет тона *добавляется* к исходным цветам текстуры и к цвету света. Под ярким белым светом спрайт будет выглядеть почти белым, а его тонирующий цвет (пурпурный) проявится в тенях или при слабом освещении.
* **.setTintFill()** — это **замещающее** тонирование. Цвет тона *полностью заменяет* исходный цвет текстуры (пиксели становятся оттенками указанного цвета), а затем на эту монохромную основу накладывается свет. Поэтому под белым светом такой спрайт останется именно пурпурным, а не белым.
Визуально в примере средний спрайт (tint) под светом будет почти белым, а правый (tintFill) — ярко-пурпурным.
Что попробовать дальше
Метод .setTintFill() — это мощный инструмент для объектов, цвет которых не должен «вымываться» ярким динамическим светом, например, для неоновых вывесок или магических эффектов. .setTint() лучше подходит для обычных объектов, где свет должен влиять естественно. Попробуйте изменить интенсивность света, его цвет или использовать текстуры с альфа-каналом, чтобы увидеть, как по-разному ведут себя эти два типа тонирования в сложных световых сценах.
