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

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

Версия 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('logo', 'assets/sprites/phaser3-logo.png');
    }

    create ()
    {
        const container1 = this.add.container(400, 100);
        const container2 = this.add.container(400, 300);
        const container3 = this.add.container(400, 500);

        const image1 = this.add.image(0, 0, 'logo').setInteractive();
        const image2 = this.add.image(0, 0, 'logo').setInteractive();
        const image3 = this.add.image(0, 0, 'logo').setInteractive();

        container1.add(image1);
        container2.add(image2);
        container3.add(image3);

        const text = this.add.text(10, 10, '', { font: '16px Courier', fill: '#00ff00' });

        image1.on('pointerover', () =>
        {
            text.setText('Over Image 1');
        });

        image2.on('pointerover', () =>
        {
            text.setText('Over Image 2');
        });

        image3.on('pointerover', () =>
        {
            text.setText('Over Image 3');
        });

        //  Ignore container2
        this.cameras.main.ignore(container2);
    }
}

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

const game = new Phaser.Game(config);

Основная логика примера

В примере создается сцена с тремя контейнерами, каждый из которых содержит интерактивное изображение логотипа Phaser. При наведении курсора на любое изображение в верхнем левом углу появляется текст, указывающий, на какой именно объект наведен курсор.

Ключевой момент — вызов this.cameras.main.ignore(container2);. Эта инструкция заставляет главную камеру игнорировать весь контейнер container2 и все его дочерние элементы. Давайте разберем код по шагам.

Создание контейнеров и добавление изображений

Сначала создаются три контейнера на разных вертикальных позициях (Y = 100, 300, 500). Внутри каждого контейнера создается и добавляется изображение с логотипом. Важно отметить, что координаты изображений задаются относительно их родительского контейнера (0, 0).

const container1 = this.add.container(400, 100);
const container2 = this.add.container(400, 300);
const container3 = this.add.container(400, 500);

const image1 = this.add.image(0, 0, 'logo').setInteractive();
const image2 = this.add.image(0, 0, 'logo').setInteractive();
const image3 = this.add.image(0, 0, 'logo').setInteractive();

container1.add(image1);
container2.add(image2);
container3.add(image3);

Метод .setInteractive() делает каждое изображение чувствительным к событиям ввода, таким как pointerover (наведение курсора).

Обработка событий и вывод информации

Для каждого изображения назначается обработчик события pointerover. При наведении курсора текст в левом верхнем углу сцены обновляется, показывая номер активного изображения. Это помогает визуально подтвердить интерактивность объектов.

const text = this.add.text(10, 10, '', { font: '16px Courier', fill: '#00ff00' });

image1.on('pointerover', () => {
    text.setText('Over Image 1');
});
// ... Аналогично для image2 и image3

Включение игнорирования для контейнера

Самая важная строка в этом примере — вызов метода ignore() у главной камеры. В качестве аргумента передается ссылка на контейнер, который нужно скрыть.

this.cameras.main.ignore(container2);

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

Практическое применение и нюансы

Метод ignore() — это не то же самое, что установка setVisible(false) для объекта. Объект остается частью сцены, обновляется (update), но просто не рисуется конкретной камерой. Это позволяет: * **Эффективно скрывать группы объектов:** Игнорирование контейнера мгновенно скрывает все его содержимое. * **Создавать слои видимости:** Можно иметь несколько камер и настраивать, какие объекты видит каждая из них. * **Оптимизировать производительность:** Временное игнорирование тяжелых групп объектов может повысить FPS.

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

// Прекратить игнорировать container2
this.cameras.main.ignore(container2, false);
// ИЛИ сбросить все игнорирования для камеры
// this.cameras.main.resetIgnore();

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

Метод camera.ignore() — это точный инструмент для управления видимостью объектов через камеру в Phaser. Он особенно эффективен для работы с контейнерами, позволяя массово скрывать или показывать сложные группы игровых сущностей. **Идеи для экспериментов:** 1. Создайте вторую камеру (this.cameras.add) и настройте разный набор игнорируемых контейнеров для главной и дополнительной камер. Это основа для picture-in-picture или сложных UI. 2. Динамически включайте и выключайте игнорирование контейнера по таймеру или событию (например, нажатию клавиши), создавая эффект мигания для группы объектов. 3. Проверьте, как игнорирование контейнера влияет на дочерние объекты с собственными физическими телами (physics.add.sprite). Останется ли тело активным в физическом мире?