О чем этот пример

Создание сложных визуальных эффектов в играх часто требует маскирования объектов. Ручное управление масками через `setMask` может быть громоздким, особенно при работе с несколькими объектами. Встроенный метод `Phaser.Actions.AddMaskShape` автоматизирует этот процесс, позволяя быстро добавлять геометрические маски к изображениям с гибкими настройками. Эта статья покажет, как использовать этот инструмент для создания разнообразных эффектов обрезки и выделения частей спрайтов.

Версия 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('prometheus', 'assets/pics/Prometheus Brings Fire To Mankind.jpg');
    }

    create ()
    {
        const prometheus1 = this.add.image(200, 150, 'prometheus').setScale(0.5);
        const prometheus2 = this.add.image(600, 150, 'prometheus').setScale(0.5);
        const prometheus3 = this.add.image(200, 450, 'prometheus').setScale(0.5);
        const prometheus4 = this.add.image(600, 450, 'prometheus').setScale(0.5);

        Phaser.Actions.AddMaskShape(prometheus1, { useInternal: true });
        Phaser.Actions.AddMaskShape(prometheus2, { useInternal: true, scaleMode: -1 });
        Phaser.Actions.AddMaskShape(prometheus3, { useInternal: true, invert: true, shape: 'rectangle', region: {
            x: 260,
            y: 140,
            width: prometheus3.width - 600,
            height: 20
        } });
        Phaser.Actions.AddMaskShape(prometheus4, { useInternal: true, scaleMode: 1 });
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    backgroundColor: '#2f3640',
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

Что делает AddMaskShape?

Phaser.Actions.AddMaskShape — это статический метод, который автоматически создаёт и применяет геометрическую маску к переданному игровому объекту. В отличие от ручного создания масок, этот метод инкапсулирует логику создания фигуры (прямоугольник или эллипс) и её привязки к объекту.

Ключевые параметры метода: - useInternal: true — указывает, что маска должна управляться самим объектом и уничтожаться вместе с ним. - shape — тип фигуры ('rectangle' или 'ellipse'). По умолчанию — эллипс. - region — объект с полями `x,y,width,height`, определяющий область маски в координатах объекта. - scaleMode — режим масштабирования маски относительно объекта. - invert — инвертирование маски (показывать скрытую часть).

Базовое применение: простая эллиптическая маска

В примере к первому изображению применяется маска с настройками по умолчанию. Это создаёт эллиптическую маску, которая обрезает изображение по границам самого спрайта.

Phaser.Actions.AddMaskShape(prometheus1, { useInternal: true });

Поскольку параметры shape и region не указаны, используется эллипс, размер которого соответствует ширине и высоте изображения prometheus1. Параметр useInternal: true гарантирует, что маска будет автоматически удалена при уничтожении изображения, предотвращая утечки памяти.

Управление режимами масштабирования: scaleMode

Параметр scaleMode определяет, как маска реагирует на изменение масштаба объекта. В примере это демонстрируется на втором и четвёртом изображениях.

// Маска не масштабируется с объектом
Phaser.Actions.AddMaskShape(prometheus2, { useInternal: true, scaleMode: -1 });

// Маска масштабируется пропорционально объекту
Phaser.Actions.AddMaskShape(prometheus4, { useInternal: true, scaleMode: 1 });

При scaleMode: -1 маска сохраняет свой исходный размер, даже если объект prometheus2 масштабируется (в данном случае через setScale(0.5)). При scaleMode: 1 маска масштабируется вместе с объектом, сохраняя относительные пропорции. Режим `0` (по умолчанию) означает, что маска масштабируется только при прямом изменении её свойств.

Прямоугольная маска с кастомной областью и инверсией

Третье изображение демонстрирует более сложную конфигурацию: прямоугольную маску с явно заданной областью и инвертированием.

Phaser.Actions.AddMaskShape(prometheus3, {
    useInternal: true,
    invert: true,
    shape: 'rectangle',
    region: {
        x: 260,
        y: 140,
        width: prometheus3.width - 600,
        height: 20
    }
});

Здесь shape: 'rectangle' меняет форму маски. Область region задаёт прямоугольник с отступом 260x140 от левого верхнего угла изображения и шириной, рассчитанной динамически (prometheus3.width - 600). Ключевой параметр invert: true инвертирует маску: теперь видимой остаётся область *вне* заданного прямоугольника, а внутри него изображение становится прозрачным. Этот приём полезен для создания эффектов «вырезания» или подсветки определённых зон.

Что попробовать дальше

Phaser.Actions.AddMaskShape — это мощный инструмент для быстрого прототипирования визуальных эффектов, связанных с обрезкой изображений. Он избавляет от boilerplate-кода при создании масок. Для экспериментов попробуйте анимировать параметры region (например, изменяя width или `x` в цикле) для создания эффекта постепенного открытия изображения. Также можно комбинировать несколько масок на одном объекте, последовательно применяя метод с разными областями и режимами инверсии, чтобы создавать сложные составные формы.