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

В сложных игровых интерфейсах или многопользовательских режимах часто требуется показывать разным игрокам или интерфейсным камерам разные наборы игровых объектов. Phaser 3 предоставляет для этого мощный и простой инструмент — метод `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 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);

        //  Camera 1 will render everything

        //  Camera 2 will ignore the images
        cam2.ignore([ image1, image2 ]);

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

        //  Camera 4 will ignore the text
        cam4.ignore([ text1, text2 ]);
    }
}

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

const game = new Phaser.Game(config);

Создание нескольких камер

В Phaser 3 у каждой сцены есть главная камера (this.cameras.main), но вы можете создать дополнительные. Метод this.cameras.add() принимает координаты X, Y, ширину и высоту вьюпорта (области отображения).

В примере мы создаем четыре камеры, разбивая экран 800x600 на четыре квадранта по 400x300 пикселей. Каждой камере задается свой цвет фона для наглядности.

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);

Создание игровых объектов для теста

Чтобы продемонстрировать работу метода ignore(), в сцене создается несколько объектов разных типов: спрайты, тексты, bitmap-текст и графика. Это важно, потому что метод работает с любыми объектами, наследующими от Phaser.GameObjects.GameObject.

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);

Принцип работы метода ignore()

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

Метод принимает как одиночный объект, так и массив объектов. В нашем примере: - **cam1** (главная) отображает все объекты по умолчанию. - **cam2** игнорирует оба спрайта. - **cam3** игнорирует графический объект. - **cam4** игнорирует оба текстовых объекта.

//  Camera 2 игнорирует изображения
cam2.ignore([ image1, image2 ]);

//  Camera 3 игнорирует Graphics
cam3.ignore(graphics);

//  Camera 4 игнорирует текст
cam4.ignore([ text1, text2 ]);

Обратная сторона: метод clearIgnore()

Phaser 3 симметрично предоставляет метод camera.clearIgnore(). Он удаляет объект или массив объектов из списка игнорируемых для данной камеры, после чего она снова начинает их отрисовывать.

Это полезно для динамического управления видимостью. Например, вы можете временно скрыть интерфейсные элементы во время кат-сцены, а затем вернуть их.

//  Камера снова начнет отрисовывать image1 и image2
cam2.clearIgnore([ image1, image2 ]);

//  Камера снова начнет отрисовывать графический объект
cam3.clearIgnore(graphics);

Практическое применение в играх

1. **Сплит-скрин для мультиплеера:** Каждому игроку — своя камера, которая следует за его персонажем. Вы можете сделать так, чтобы камера игрока А игнорировала его собственный HUD (здоровье, аммуницию), но отображала HUD игрока Б как часть игрового мира, и наоборот. 2. **Миникарта:** Создайте маленькую камеру в углу экрана, которая следует за игроком. С помощью ignore() вы можете скрыть от нее все детали интерфейса и эффекты, оставив только карту и важные маркеры. 3. **Режим наблюдения (Spectator):** Камера наблюдателя может игнорировать служебные объекты или подсказки, видимые только активным игрокам.

Важно помнить, что игнорируемые объекты **не удаляются из сцены**, их физические тела продолжают работать, а логика обновляться.

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

Метод ignore() — это эффективный способ декомпозиции сложных сцен, позволяющий разным камерам показывать разные аспекты игрового мира. Он не нагружает производительность, так как просто исключает объекты из конвейера отрисовки конкретной камеры. **Идеи для экспериментов:** 1. Создайте камеру для отладки, которая игнорирует все игровые объекты, но отображает только hitbox-ы и логические маркеры. 2. Реализуйте систему "взгляда персонажа", где дополнительная камера, прикрепленная к нему, игнорирует самого персонажа, чтобы он не загораживал обзор. 3. Поэкспериментируйте с динамическим вызовом ignore() и clearIgnore() в ответ на игровые события (например, получение предмета "невидимость").