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

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

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class Example extends Phaser.Scene
{
    constructor ()
    {
        super();
        this.iter = 0;

    }

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

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

        this.cameras.main.setSize(400, 300);
    
        this.camera0 = this.cameras.main;
        this.camera1 = this.cameras.add(400, 0, 400, 300);
        this.camera2 = this.cameras.add(0, 300, 400, 300);
        this.camera3 = this.cameras.add(400, 300, 400, 300);
    }

    update () 
    {
        this.camera0.zoom = 0.5 + Math.abs(Math.sin(this.iter));
        this.camera0.scrollX = Math.sin(this.iter) * 400;
            
        this.camera1.rotation = this.iter;
    
        this.camera2.scrollX = Math.cos(this.iter) * 100;
        this.camera2.scrollY = Math.sin(this.iter) * 100;
        this.camera2.zoom = 0.5 + Math.abs(Math.sin(this.iter));
        this.camera2.rotation = -this.iter;
    
        this.camera3.zoom = 0.5 + Math.abs(Math.sin(this.iter));
        this.iter += 0.01;
    }
}

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

const game = new Phaser.Game(config);

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

Вся логика примера размещена в классе сцены Example. В конструкторе инициализируется переменная iter, которая будет использоваться как счётчик для анимации.

В методе preload загружается одно изображение. Обратите внимание, что базовый URL задается через this.load.setBaseURL, что позволяет указывать относительные пути для ассетов.

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

Создание основного изображения и камер

В методе create создается спрайт изображения в центре игрового мира. Это будет единственный объект, который будут отображать все камеры.

Затем основная камера (this.cameras.main) уменьшается до размера 400x300 пикселей. Это важно, потому что далее мы добавим еще три камеры, и они не должны перекрывать основную.

После этого создаются три дополнительные камеры с помощью метода this.cameras.add. Каждая новая камера создается с указанием координат (x, y) и размеров (width, height). В результате мы получаем четыре квадранта на экране, каждый со своей камерой.

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

this.cameras.main.setSize(400, 300);

this.camera0 = this.cameras.main;
this.camera1 = this.cameras.add(400, 0, 400, 300);
this.camera2 = this.cameras.add(0, 300, 400, 300);
this.camera3 = this.cameras.add(400, 300, 400, 300);

Динамическое управление камерами в update

Сердце примера — метод update, который выполняется каждый кадр. Здесь переменная iter плавно увеличивается, и на её основе вычисляются параметры для каждой камеры.

- **Камера 0 (верхний левый квадрант)**: Её зум (zoom) пульсирует от 0.5 до 1.5, а положение (scrollX) плавно смещается по горизонтали. Это создает эффект "дыхания" и панорамирования. - **Камера 1 (верхний правый квадрант)**: Вращается (rotation) вокруг своей центральной точки, демонстрируя, как камера может поворачивать весь свой вид. - **Камера 2 (нижний левый квадрант)**: Самый сложный эффект. Камера одновременно движется по кругу (через scrollX и scrollY), пульсирует по зуму и вращается в обратную сторону. Это показывает, как свойства можно комбинировать. - **Камера 3 (нижний правый квадрант)**: Просто повторяет пульсирующий зум камеры 0.

Ключевой момент: каждая камера управляется независимо, изменяя только свою часть экрана.

this.camera0.zoom = 0.5 + Math.abs(Math.sin(this.iter));
this.camera0.scrollX = Math.sin(this.iter) * 400;

this.camera1.rotation = this.iter;

this.camera2.scrollX = Math.cos(this.iter) * 100;
this.camera2.scrollY = Math.sin(this.iter) * 100;
this.camera2.zoom = 0.5 + Math.abs(Math.sin(this.iter));
this.camera2.rotation = -this.iter;

this.camera3.zoom = 0.5 + Math.abs(Math.sin(this.iter));
this.iter += 0.01;

Конфигурация игры и запуск

Код запуска игры стандартен. Конфигурационный объект config определяет тип рендерера, элемент-контейнер, используемую сцену и общий размер игрового окна. Важно, что общий размер (800x600) в два раза превышает размер каждой отдельной камеры (400x300), что и позволяет разместить их в четыре квадранта.

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

const game = new Phaser.Game(config);

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

Этот пример наглядно демонстрирует мощь и гибкость системы камер в Phaser. Вы можете не просто следить за игроком, а создавать сложные композиции из нескольких видов. Для экспериментов попробуйте: изменить логику движения камер, привязать камеры к разным игровым объектам, добавить эффекты вроде дрожания (shake) или плавного перемещения (pan), или использовать маски камер для создания нестандартных форм обзора.