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

В разработке игр часто возникает необходимость отображать разные элементы интерфейса или игрового мира в отдельных областях экрана. Например, вы хотите показать карту в одном углу, инвентарь в другом, а основное действие — по центру. Phaser позволяет создавать несколько камер с разными областями видимости (вьюпортами). Но что, если нужно, чтобы определенные игровые объекты отображались только в некоторых камерах, а в других — нет? Этот пример демонстрирует мощный метод `camera.ignore()`, который позволяет исключать целые группы объектов, объединенные в контейнеры, из рендеринга конкретной камерой. Это особенно полезно для создания сложных HUD, разделения экрана на несколько логических областей или реализации картинки-в-картинке.

Версия 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('asuna', 'assets/sprites/asuna_by_vali233.png');
        this.load.image('brain', 'assets/sprites/brain.png');
        this.load.bitmapFont('desyrel', 'assets/fonts/bitmap/desyrel.png', 'assets/fonts/bitmap/desyrel.xml');
    }

    create () 
    {
        //  We'll have 4 cameras in a quad arrangement
        const cam1 = this.cameras.main.setViewport(0, 0, 400, 300).setBackgroundColor(0x0099cc);
        const cam2 = this.cameras.add(400, 0, 400, 300).setBackgroundColor(0x0033ff);
        const cam3 = this.cameras.add(0, 300, 400, 300).setBackgroundColor(0x9966ff);
        const cam4 = this.cameras.add(400, 300, 400, 300).setBackgroundColor(0xcc99ff);

        //  Now create a few Game Objects
        const container1 = this.add.container();
        const container2 = this.add.container();
        const container3 = this.add.container();

        const image1 = this.add.image(40, 100, 'asuna');
        const image2 = this.add.image(160, 100, 'brain');
        const text1 = this.add.text(20, 190, 'Camera Ignore', { fill: '#ffffff' });
        const text2 = this.add.bitmapText(20, 220, 'desyrel', 'Camera Ignore', 32);
        const graphics = this.add.graphics().fillStyle(0xefefef, 1).fillRect(270, 40, 80, 40).fillTriangle(200, 180, 360, 110, 360, 250);

        container1.add([ image1, image2 ]);
        container2.add(graphics);
        container3.add([ text1, text2 ]);

        //  Camera 1 will render everything

        //  Camera 2 will ignore the images
        cam2.ignore(container1);

        //  Camera 3 will ignore the Graphics
        cam3.ignore(container2);

        //  Camera 4 will ignore the text
        cam4.ignore(container3);
    }
}

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

const game = new Phaser.Game(config);

Настройка сцены и создание камер

В методе create() сцены мы настраиваем рабочее пространство. Вместо одной основной камеры создается четыре, каждая из которых занимает свой квадрант экрана размером 800x600 пикселей. Основная камера (this.cameras.main) и три дополнительные камеры, созданные с помощью this.cameras.add(), получают свои вьюпорты и фоновые цвета для наглядности.

const cam1 = this.cameras.main.setViewport(0, 0, 400, 300).setBackgroundColor(0x0099cc);
const cam2 = this.cameras.add(400, 0, 400, 300).setBackgroundColor(0x0033ff);
const cam3 = this.cameras.add(0, 300, 400, 300).setBackgroundColor(0x9966ff);
const cam4 = this.cameras.add(400, 300, 400, 300).setBackgroundColor(0xcc99ff);

Создание игровых объектов и их группировка в контейнеры

Далее создаются различные игровые объекты: два изображения (image1, image2), текстовый объект (text1), bitmap-текст (text2) и графический объект (graphics), который рисует прямоугольник и треугольник. Ключевой момент — эти объекты не добавляются на сцену по отдельности. Вместо этого они группируются в три контейнера с помощью this.add.container().

Контейнеры (container1, container2, container3) — это специальные объекты Phaser, которые могут содержать в себе других потомков (другие игровые объекты). Это позволяет управлять группой объектов как единым целым.

const container1 = this.add.container();
const container2 = this.add.container();
const container3 = this.add.container();

// ... создание image1, image2, text1, text2, graphics ...

container1.add([ image1, image2 ]);
container2.add(graphics);
container3.add([ text1, text2 ]);

После этих операций все объекты становятся видимыми для камеры по умолчанию, так как они добавлены в контейнеры, которые, в свою очередь, автоматически добавлены в список отображения сцены.

Применение метода ignore() к камерам

Здесь проявляется основная функциональность примера. Метод ignore() камеры принимает игровой объект и исключает его (и всех его потомков) из списка рендеринга для этой конкретной камеры.

- **Камера 1 (cam1)**: Ничего не игнорирует. Она отображает все объекты со сцены, так как является основной и на нее не вызван метод ignore. Это эталонный вид. - **Камера 2 (cam2)**: Игнорирует container1. Это значит, что изображения Асуны и мозга (image1, image2) не будут отрисованы в правом верхнем квадранте. - **Камера 3 (cam3)**: Игнорирует container2. В левом нижнем квадранте не будет видно графических фигур (прямоугольника и треугольника). - **Камера 4 (cam4)**: Игнорирует container3. В правом нижнем квадранте исчезнут оба текстовых объекта.

//  Camera 2 will ignore the images
cam2.ignore(container1);

//  Camera 3 will ignore the Graphics
cam3.ignore(container2);

//  Camera 4 will ignore the text
cam4.ignore(container3);

Важно понимать, что ignore() применяется к самому контейнеру. Поскольку изображения являются его дочерними элементами, они также автоматически исключаются из рендеринга. Это избавляет от необходимости перебирать все объекты в группе и игнорировать каждый по отдельности.

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

Использование camera.ignore() в связке с контейнерами предоставляет чистый и эффективный способ управления видимостью групп объектов для разных областей отображения. Это мощный инструмент для организации сложных сцен с множеством камер. **Идеи для экспериментов:** 1. Попробуйте игнорировать не целый контейнер, а одиночный игровой объект (например, только image1). 2. Создайте камеру, которая игнорирует все, кроме одного контейнера, используя ignore() для всех остальных групп объектов. 3. Динамически управляйте игнорированием во время игры. Например, по нажатию клавиши вызовите cam2.ignore(container1) снова (игнорирование уже установлено) или его противоположность — cam2.ignore(container1, false) — чтобы вернуть объекты в рендеринг. 4. Проверьте, как работает вложенность: создайте контейнер внутри контейнера и попробуйте игнорировать родительский.