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

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

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

Живой запуск

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

Исходный код


class MainScene extends Phaser.Scene
{

    constructor()
    {
        super({ key: "MainScene" });
    }

    init() {
        this.cameras.main.setSize(400, 300).setName('1').setBackgroundColor(0xff0000);

        this.cameras.add(400, 0, 400, 300).setName('2').setBackgroundColor(0x00ffff);
        this.cameras.add(0, 300, 400, 300).setName('3').setBackgroundColor(0x0000ff);
        this.cameras.add(400, 300, 400, 300).setName('4').setBackgroundColor(0xffff00);
    }

    preload() {
        
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image("earth", "assets/pics/ayu.png");

        this.load.scripts('inspector', [
            'https://cdn.jsdelivr.net/npm/tweakpane@3.1.0',
            'https://cdn.jsdelivr.net/npm/phaser-plugin-inspector@2.4.1',
        ]);
    }

    create ()
    {
        this.earth = this.add.image(200, 150, "earth");
        // const gui = new dat.GUI();
        // for (let i = 0; i < this.cameras.cameras.length; i++)
        // {
        //     const camera = this.cameras.cameras[ i ];
        //     gui.add(camera, 'alpha', 0.1, 1).step(0.1);
        // }
    }

    update (time)
    {
        this.earth.rotation += 0.005;
        this.earth.y = this.earth.y + Math.sin(time / 1000 * 2)
    }

}

const config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    pixelArt: true,
    scale: {
        mode: Phaser.Scale.FIT,
        autoCenter: Phaser.Scale.CENTER_BOTH
    },
    scene: [ MainScene ]
};

const game = new Phaser.Game(config);

Настройка основной и дополнительных камер

В Phaser каждая сцена (Scene) по умолчанию имеет одну главную камеру, доступную через this.cameras.main. Её свойства можно изменять. В методе init() нашего примера происходит первоначальная настройка.

Сначала мы меняем размер и фон главной камеры. Затем создаём три дополнительные камеры. Метод this.cameras.add() принимает координаты X, Y, ширину и высоту новой области просмотра. Каждой камере задаётся уникальное имя и цвет фона для наглядности.

init() {
    this.cameras.main.setSize(400, 300).setName('1').setBackgroundColor(0xff0000);

    this.cameras.add(400, 0, 400, 300).setName('2').setBackgroundColor(0x00ffff);
    this.cameras.add(0, 300, 400, 300).setName('3').setBackgroundColor(0x0000ff);
    this.cameras.add(400, 300, 400, 300).setName('4').setBackgroundColor(0xffff00);
}

В результате мы получаем экран 800x600, разделённый на четыре квадранта по 400x300 пикселей каждый, со своей камерой в каждом. Цвет фона (setBackgroundColor) виден только там, где нет игровых объектов.

Создание и анимация общего объекта

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

В методе create() мы создаём один-единственный спрайт — изображение Земли. Обратите внимание: он добавляется в координатах (200, 150) относительно мировых координат сцены. Поскольку главная камера (камера №1) теперь смотрит только на область (0,0,400,300) мировых координат, этот спрайт окажется в её центре. Для остальных камер он будет находиться в одном и том же мировом положении.

create ()
{
    this.earth = this.add.image(200, 150, "earth");
}

В методе update() этому спрайту добавляется простая анимация: постоянное вращение и плавное движение по вертикали с использованием синуса. Эти изменения применяются к самому объекту this.earth и автоматически видны во всех четырёх областях просмотра.

update (time)
{
    this.earth.rotation += 0.005;
    this.earth.y = this.earth.y + Math.sin(time / 1000 * 2)
}

Конфигурация игры и масштабирование

Важную роль играет настройка масштабирования (scale) в конфигурационном объекте игры. В примере используется режим Phaser.Scale.FIT, который гарантирует, что игровая область (800x600) будет вписана в окно браузера с сохранением пропорций. Phaser.Scale.CENTER_BOTH центрирует отрисованную область по горизонтали и вертикали.

const config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    pixelArt: true,
    scale: {
        mode: Phaser.Scale.FIT,
        autoCenter: Phaser.Scale.CENTER_BOTH
    },
    scene: [ MainScene ]
};

Благодаря этим настройкам, даже если физический размер окна браузера изменится, сетка из четырёх камер останется корректной и пропорциональной. Флаг pixelArt: true включает специальное сглаживание для пиксельной графики, что может быть полезно для ретро-стиля.

Практическое применение и контроль

Зачем создавать несколько камер? Вот несколько сценариев:

* **Split-Screen (разделённый экран)**: Каждая камера следует за своим игроком в кооперативной игре. * **Миникарта**: Одна камера показывает общий вид уровня в углу экрана. * **Статичный UI**: Интерфейс (здоровье, боезапас) можно отрисовывать в отдельной камере, которая не подвержена встряскам (shake) или скроллу основной камеры. * **Эффекты зеркал или видеонаблюдения**: Камера может быть направлена на другую часть сцены и отрисована на текстуре.

Каждой камерой можно управлять независимо. Вы можете:

* **Менять её область просмотра в мире** с помощью setScroll. * **Применять визуальные эффекты**: setAlpha (прозрачность), setZoom (масштаб), setRotation (вращение). * **Назначавать объекты конкретным камерам**, чтобы они были видны только в них, используя свойство visible объекта и методы камеры ignore.

Закомментированный код в примере намекает на возможность динамического изменения прозрачности (alpha) каждой камеры через панель отладки.

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

Система камер в Phaser — это мощный и гибкий инструмент, выходящий далеко за рамки простого следования за игроком. Разделение экрана на несколько независимых областей просмотра открывает возможности для сложных механик и улучшения пользовательского опыта. **Идеи для экспериментов:** 1. Заставьте каждую камеру следовать за отдельным спрайтом, создав простой split-screen. 2. Поэкспериментируйте с эффектами камер: добавьте setZoom к одной и setRotation к другой в цикле update. 3. Создайте объект (например, снаряд) и сделайте его видимым только для одной из камер с помощью camera.ignore(this.bullet) для остальных.