О чем этот пример
Маски — мощный инструмент в разработке игр для создания эффектов, скрытия частей объектов или нестандартных переходов. В Phaser есть несколько типов масок. В этом примере мы рассмотрим BitmapMask, использующую RenderTexture в качестве источника. Это позволяет создавать маски, которые можно динамически изменять во время выполнения игры, например, рисовать на них или заполнять цветом. Практическое понимание этого механизма открывает двери к созданию сложных визуальных эффектов, таких как постепенное проявление объектов, эффекты "тумана войны" или нестандартные формы отсечения.
Версия 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('ayu', 'assets/pics/ayu.png');
}
create ()
{
this.scale.resize(800, 600);
const sprite = this.add.sprite(400, 300, 'ayu');
const rt = this.make.renderTexture({x: 0, y: 0, width: 800, height: 600, add: false}).setOrigin(0.0);
const mask = new Phaser.Display.Masks.BitmapMask(this, rt);
console.log(this.renderer);
rt.fill(0x000000, 1);
this.input.on('pointerdown', pointer => {
sprite.setMask(mask);
});
}
}
const config = {
type: Phaser.AUTO,
width: 200,
height: 150,
backgroundColor: '#0a440a',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Инициализация сцены и загрузка ресурсов
В методе preload мы загружаем одно изображение, которое будет использоваться в качестве спрайта. Обратите внимание на использование this.load.setBaseURL, которое задаёт базовый URL для всех последующих загрузок, что удобно для примеров.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('ayu', 'assets/pics/ayu.png');
}
Создание основных объектов
В методе create происходит основная настройка. Сначала мы изменяем размер игрового холста с помощью this.scale.resize. Затем создаём спрайт в центре экрана.
Ключевой момент — создание RenderTexture (rt). RenderTexture — это специальный текстурируемый объект, на котором можно рисовать, как на холсте. Мы создаём его размером с наше игровое окно (800x600) и устанавливаем точку начала координат в левый верхний угол (setOrigin(0.0)).
create ()
{
this.scale.resize(800, 600);
const sprite = this.add.sprite(400, 300, 'ayu');
const rt = this.make.renderTexture({x: 0, y: 0, width: 800, height: 600, add: false}).setOrigin(0.0);
}
Создание BitmapMask и её подготовка
Далее мы создаём объект BitmapMask. Этот тип маски использует другую текстуру (в нашем случае — rt) в качестве шаблона. Области, где текстура маски непрозрачны, будут видны на исходном спрайте. Прозрачные или чёрные области — скроют соответствующие части спрайта.
Сразу после создания маски мы заполняем всю RenderTexture (rt) сплошным чёрным цветом с помощью метода fill. Поскольку в формате цвета 0x000000 соответствует чёрному (полная прозрачность в контексте маски), это означает, что если сейчас применить маску, спрайт станет полностью невидимым.
const mask = new Phaser.Display.Masks.BitmapMask(this, rt);
rt.fill(0x000000, 1);
Динамическое применение маски
Маска применяется к спрайту не сразу, а по событию клика мыши (pointerdown). При клике вызывается метод sprite.setMask(mask), который связывает созданную маску со спрайтом. Поскольку маска заполнена чёрным цветом, спрайт моментально исчезнет с экрана после клика.
Этот паттерн полезен для создания триггерных эффектов, например, когда игрок нажимает на предмет, чтобы он растворился.
this.input.on('pointerdown', pointer => {
sprite.setMask(mask);
});
Конфигурация игры и потенциал для экспериментов
Конфиг игры задаёт начальный небольшой размер окна (200x150), который затем меняется в create. Это демонстрирует, что масштабирование и работа с масками независимы от начальных параметров.
const config = {
type: Phaser.AUTO,
width: 200,
height: 150,
backgroundColor: '#0a440a',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Сила этого подхода в том, что RenderTexture (rt) — это динамическая текстура. Вместо одноразового fill вы можете:
* Рисовать на ней фигуры (rt.fillRect, rt.strokeRect) в ответ на действия игрока.
* Копировать на неё части других текстур (rt.draw).
* Постепенно очищать её (заливая прозрачным белым 0xffffff), создавая эффект "проявления" спрайта из-под маски.
Что попробовать дальше
Использование BitmapMask в связке с RenderTexture предоставляет гибкий инструмент для создания динамических эффектов отсечения видимости в Phaser. Вы можете программно менять содержимое маски в реальном времени, реагируя на игровые события. Для экспериментов попробуйте изменить цвет заливки rt.fill на белый (0xffffff) — спрайт останется видимым. Или добавьте в обработчик pointermove рисование кругов на rt белым цветом, чтобы "стирать" маску под курсором мыши, создавая эффект обнаружения скрытого изображения.
