О чем этот пример
В игровых проектах часто требуется отображать мини-карту или предоставлять игроку альтернативный вид на локацию. Phaser позволяет легко решить эту задачу, используя систему камер. В этой статье мы разберем пример создания дополнительной камеры для отображения уменьшенной копии тайловой карты с независимым управлением. Этот подход полезен не только для мини-карт, но и для систем наблюдения, разделенного экрана или камеры-дрона.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
smallCamera;
controls;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('tiles', 'assets/tilemaps/tiles/dangerous-kiss-x2.png');
this.load.tilemapTiledJSON('map', 'assets/tilemaps/maps/dangerous-kiss.json');
}
create ()
{
const map = this.make.tilemap({ key: 'map' });
// The map was created with 8x8 tiles, but we want to load it with a 2x high resolution tileset
map.setBaseTileSize(16, 16);
const tileset = map.addTilesetImage('DangerousKiss_bank.png', 'tiles', 16, 16);
const layer = map.createLayer('ShoeBox Tile Grab', tileset, 0, 0);
const cursors = this.input.keyboard.createCursorKeys();
this.smallCamera = this.cameras.add(800 - 320, 20, 300, 300);
this.smallCamera.rotation = 0.2;
this.smallCamera.zoom = 0.5;
this.smallCamera.setBackgroundColor('rgba(0, 0, 0, 1)');
const controlConfig = {
camera: this.smallCamera,
left: cursors.left,
right: cursors.right,
up: cursors.up,
down: cursors.down,
acceleration: 0.04,
drag: 0.0005,
maxSpeed: 0.7
};
this.controls = new Phaser.Cameras.Controls.SmoothedKeyControl(controlConfig);
this.smallCamera.setBounds(0, 0, layer.width, layer.height);
}
update (time, delta)
{
this.controls.update(delta);
}
}
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
pixelArt: true,
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и загрузка ресурсов
Класс сцены Example расширяет Phaser.Scene. В нем объявляются две переменные для хранения ссылок на вторую камеру и ее контроллер.
В методе preload загружаются необходимые ресурсы: изображение тайлсета и файл карты в формате JSON, созданный в редакторе Tiled. Обратите внимание на использование setBaseURL для указания корневого пути к ресурсам из репозитория примеров Phaser.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('tiles', 'assets/tilemaps/tiles/dangerous-kiss-x2.png');
this.load.tilemapTiledJSON('map', 'assets/tilemaps/maps/dangerous-kiss.json');
}
Создание тайловой карты и основной сцены
В методе create происходит основная инициализация. Сначала создается объект тайловой карты (Tilemap) из загруженных данных.
Ключевой момент: исходная карта была создана с тайлами 8x8 пикселей, но загружается тайлсет с удвоенным разрешением (16x16). Метод setBaseTileSize(16, 16) сообщает движку о новом размере базового тайла для корректного отображения.
Затем тайлсет добавляется на карту, и создается слой для отрисовки.
const map = this.make.tilemap({ key: 'map' });
map.setBaseTileSize(16, 16);
const tileset = map.addTilesetImage('DangerousKiss_bank.png', 'tiles', 16, 16);
const layer = map.createLayer('ShoeBox Tile Grab', tileset, 0, 0);
Добавление и настройка второй камеры
Основная камера в Phaser создается по умолчанию и охватывает весь холст. Мы создаем вторую, дополнительную камеру с помощью метода this.cameras.add. Ее параметры — координаты X, Y, ширина и высота области просмотра на экране.
Созданная камера smallCamera позиционируется в правом верхнем углу. Ей задается небольшой поворот (rotation), уменьшенный масштаб (zoom) и черный фон для визуального отделения от основной сцены.
this.smallCamera = this.cameras.add(800 - 320, 20, 300, 300);
this.smallCamera.rotation = 0.2;
this.smallCamera.zoom = 0.5;
this.smallCamera.setBackgroundColor('rgba(0, 0, 0, 1)');
Важно ограничить перемещение камеры пределами карты, чтобы она не уходила в пустоту. Это делается методом setBounds.
this.smallCamera.setBounds(0, 0, layer.width, layer.height);
Настройка плавного управления для камеры
Чтобы игрок мог перемещать мини-карту, нужно назначить управление. В примере используется готовый контроллер Phaser.Cameras.Controls.SmoothedKeyControl, который обеспечивает инерционное, плавное движение камеры при нажатии клавиш.
Сначала создается объект конфигурации controlConfig. В него передается ссылка на управляемую камеру (smallCamera), привязка к клавишам-стрелкам (из cursors), а также параметры ускорения, торможения и максимальной скорости.
const controlConfig = {
camera: this.smallCamera,
left: cursors.left,
right: cursors.right,
up: cursors.up,
down: cursors.down,
acceleration: 0.04,
drag: 0.0005,
maxSpeed: 0.7
};
this.controls = new Phaser.Cameras.Controls.SmoothedKeyControl(controlConfig);
Созданный контроллер необходимо обновлять каждый кадр в методе update, передавая ему дельту времени.
update (time, delta)
{
this.controls.update(delta);
}
Конфигурация игры и запуск
Инициализация игры происходит стандартно. В конфигурационном объекте важно установить флаг pixelArt: true. Это отключает линейную интерполяцию текстур при масштабировании, что сохраняет четкость пиксельной графики, особенно при уменьшении масштаба во второй камере (zoom: 0.5).
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
backgroundColor: '#2d2d2d',
parent: 'phaser-example',
pixelArt: true,
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Использование нескольких камер открывает большие возможности для геймдизайна. Вы можете не только создавать мини-карты, но и реализовывать split-screen для мультиплеера, кат-сцены с разными ракурсами или UI-элементы, привязанные к миру игры. Для экспериментов попробуйте: связать положение мини-камеры с главным героем, добавить на нее статические маркеры объектов, изменить режим смешивания (setBlendMode) для эффекта подсветки или использовать ее как прицел для снайперской винтовки.
