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

В Phaser 3 камеры — это не просто окно в игровой мир, а мощный инструмент для создания сложных визуальных эффектов. Пример с 16 камерами демонстрирует, как можно разделить экран на множество независимых областей отображения, которые показывают один и тот же объект под разными углами. Этот приём полезен для создания динамичных интерфейсов, систем наблюдения в стратегиях или для тестирования поведения объектов в разных частях сцены.

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

    create ()
    {
        this.image = this.add.image(200, 150, 'einstein');

        //  We're going to create 16 cameras in a 4x4 grid, making each 200x150 in size
        this.cameras.main.setSize(200, 150);

        for (var y = 0; y < 4; y++)
        {
            for (var x = 0; x < 4; x++)
            {
                if (x === 0 && y === 0)
                {
                    continue;
                }

                this.cameras.add(x * 200, y * 150, 200, 150);
            }
        }
    }

    update ()
    {
        this.image.rotation += 0.01;
    }
}


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

const game = new Phaser.Game(config);

Подготовка сцены и загрузка ресурса

В фазе preload мы загружаем единственное изображение, которое станет центром нашего эксперимента. Адрес загрузки устанавливается относительно базового URL.

this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('einstein', 'assets/pics/ra-einstein.png');

В create мы создаём спрайт изображения и позиционируем его в точке (200, 150). Этот объект будет вращаться в update, что наглядно покажет работу всех камер.

this.image = this.add.image(200, 150, 'einstein');

Модификация главной камеры

Перед созданием дополнительных камер важно подготовить основную. По умолчанию она занимает весь экран. С помощью метода setSize мы уменьшаем её область отображения до размеров одной ячейки будущей сетки (200x150 пикселей). Это освобождает место на экране для других камер.

this.cameras.main.setSize(200, 150);

Теперь главная камера будет отображать только левый верхний угол игрового мира, соответствующий её новой области.

Создание сетки из камер

Ключевой момент — создание 15 дополнительных камер с помощью метода this.cameras.add. Вложенные циклы проходят по сетке 4x4. Условие if (x === 0 && y === 0) пропускает создание камеры для левой верхней ячейки, так как эта область уже занята главной камерой (main).

for (var y = 0; y < 4; y++)
{
    for (var x = 0; x < 4; x++)
    {
        if (x === 0 && y === 0)
        {
            continue;
        }
        this.cameras.add(x * 200, y * 150, 200, 150);
    }
}

Каждая новая камера создаётся с указанием её позиции на экране (координаты x, y) и размеров (width, height). Умножение на размер ячейки (200 и 150) формирует аккуратную сетку. Все камеры по умолчанию смотрят на одни и те же координаты игрового мира (0,0), поэтому в каждой ячейке мы видим один и тот же вращающийся спрайт.

Анимация для наглядности

Чтобы визуально подтвердить, что все камеры показывают один и тот же динамичный объект, в методе update мы непрерывно вращаем изображение. Это сразу демонстрирует синхронность работы всех 16 областей просмотра.

update ()
{
    this.image.rotation += 0.01;
}

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

Этот пример раскрывает фундаментальный принцип работы камер в Phaser 3: они являются независимыми окнами в общую сцену. Для экспериментов попробуйте

  1. Изменить положение или размер исходного спрайта this.image и понаблюдать за реакцией всех камер одновременно
  2. Применить к разным камерам эффекты (например, setAlpha или setZoom) через получение ссылки на них из массива this.cameras.cameras
  3. Использовать этот подход для создания мини-карты или сложного разделённого экрана