О чем этот пример
В стандартном сценарии Phaser 3 у нас есть одна главная камера, которая определяет область отображения игры. Но что, если вам нужно показать одну и ту же сцену с разных ракурсов одновременно, например, для создания камер наблюдения, разделенного экрана в кооперативной игре или динамического UI-элемента? В этом примере мы разберем, как создать сетку из 32 независимых камер, каждая из которых смотрит на один и тот же вращающийся объект. Этот подход открывает путь к сложным визуальным композициям и нестандартным интерфейсам прямо в игровом мире.
Версия 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(100, 70, 'einstein');
// We're going to create 32 cameras in a 8x4 grid, making each 100x150 in size
this.cameras.main.setSize(100, 150);
for (let y = 0; y < 4; y++)
{
for (let x = 0; x < 8; x++)
{
if (x === 0 && y === 0)
{
continue;
}
this.cameras.add(x * 100, y * 150, 100, 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);
Инициализация сцены и загрузка ассета
Класс сцены Example наследуется от Phaser.Scene. В методе preload мы загружаем единственное изображение, используя this.load.setBaseURL для указания базового пути и this.load.image для загрузки файла.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('einstein', 'assets/pics/ra-einstein.png');
}
Это стандартная процедура подготовки ресурсов для сцены. Изображение будет доступно под ключом 'einstein'.
Создание основного объекта и настройка главной камеры
В методе create мы сначала добавляем изображение в сцену с помощью this.add.image. Оно будет нашим центральным объектом, за которым наблюдают все камеры.
this.image = this.add.image(100, 70, 'einstein');
Затем происходит ключевое действие: мы изменяем размер основной камеры (this.cameras.main). По умолчанию камера занимает весь холст игры (800x600 пикселей из конфига). С помощью метода setSize мы ограничиваем её область просмотра.
this.cameras.main.setSize(100, 150);
Теперь основная камера будет отображать только квадрат 100x150 пикселей в левом верхнем углу игрового мира. Важно: это не изменяет размер игрового мира, а лишь область, которую эта конкретная камера проецирует на холст.
Генерация сетки дополнительных камер
Следующий шаг — создание остальных 31 камеры с помощью двух вложенных циклов for. Цель — расположить их в виде сетки 8x4.
for (let y = 0; y < 4; y++)
{
for (let x = 0; x < 8; x++)
{
if (x === 0 && y === 0)
{
continue;
}
this.cameras.add(x * 100, y * 150, 100, 150);
}
}
Условие if (x === 0 && y === 0) пропускает создание камеры для первой ячейки сетки, так как эта позиция уже занята главной камерой, которую мы настроили ранее. Метод this.cameras.add создает новую камеру. Его параметры:
1. x * 100: X-координата *всех* камер внутри игрового мира.
2. y * 150: Y-координата *всех* камер внутри игрового мира.
3. 100: Ширина области просмотра камеры.
4. 150: Высота области просмотра камеры.
Все созданные камеры автоматически "смотрят" на одну и ту же область игрового мира, но каждая проецирует свой маленький фрагмент (100x150) на свою уникальную позицию на общем холсте игры. Так формируется сетка.
Анимация объекта и настройка игры
В методе update, который вызывается каждый кадр, мы вращаем наше изображение. Это наглядно демонстрирует, что все камеры наблюдают за одним и тем же динамичным объектом.
update ()
{
this.image.rotation += 0.01;
}
Конфигурация игры задает стандартный холст размером 800x600 пикселей, что идеально вмещает нашу сетку из 8 камер по ширине (8 * 100 = 800) и 4 по высоте (4 * 150 = 600).
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene:[ Example ]
};
const game = new Phaser.Game(config);
Что попробовать дальше
Этот пример наглядно демонстрирует мощь и гибкость системы камер Phaser 3. Вы можете создавать десятки независимых видов, управлять их свойствами (масштабом, поворотом, эффектами) отдельно и даже назначать их конкретным объектам или слоям. Для экспериментов попробуйте
- Применить к разным камерам разные визуальные эффекты через
camera.setPostPipeline - Заставить камеры следовать за разными игровыми объектами с помощью
camera.startFollow - Динамически менять размер или положение камер в реальном времени для создания "пинч-зума" или переключения видов
