О чем этот пример
Вращение камеры — мощный инструмент для создания динамичных сцен и спецэффектов в играх. В отличие от простой прокрутки, поворот камеры меняет угол обзора, позволяя имитировать наклон, головокружение персонажа или нестандартные переходы. В этой статье мы разберем готовый пример, который показывает, как настроить камеру с областью видимости больше экрана и управлять её положением и вращением с клавиатуры.
Версия 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('bg', 'assets/pics/uv-grid-diag.png');
this.load.image('block', 'assets/sprites/block.png');
}
create ()
{
this.cameras.main.setBounds(0, 0, 1024 * 2, 1024 * 2);
this.add.image(0, 0, 'bg').setOrigin(0);
this.add.image(1024, 0, 'bg').setOrigin(0);
this.add.image(0, 1024, 'bg').setOrigin(0);
this.add.image(1024, 1024, 'bg').setOrigin(0);
this.cursors = this.input.keyboard.createCursorKeys();
this.keys = this.input.keyboard.addKeys('W,A,S,D');
// this.cameras.main.originX = 1;
this.cameras.main.centerToBounds();
this.text = this.add.text(32, 32).setScrollFactor(0).setFontSize(32).setColor('#ffffff');
}
update ()
{
const cam = this.cameras.main;
this.text.setText([
'ScrollX: ' + cam.scrollX,
'ScrollY: ' + cam.scrollY,
'MidX: ' + cam.midPoint.x,
'MidY: ' + cam.midPoint.y
]);
if (this.keys.A.isDown)
{
cam.scrollX -= 6;
}
else if (this.keys.D.isDown)
{
cam.scrollX += 6;
}
if (this.keys.W.isDown)
{
cam.scrollY -= 6;
}
else if (this.keys.S.isDown)
{
cam.scrollY += 6;
}
if (this.cursors.left.isDown)
{
cam.rotation -= 0.01;
}
else if (this.cursors.right.isDown)
{
cam.rotation += 0.01;
}
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
physics: {
default: 'arcade',
},
scene: Example
};
const game = new Phaser.Game(config);
Настройка сцены и загрузка ресурсов
В методе preload мы загружаем два изображения: фон (uv-grid-diag.png) и спрайт блока. Обратите внимание, что базовый URL задается через this.load.setBaseURL, что удобно для примеров с внешними ресурсами.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/pics/uv-grid-diag.png');
this.load.image('block', 'assets/sprites/block.png');
}
В методе create первым делом расширяем границы основной камеры this.cameras.main.setBounds. Это определяет область, по которой камера может перемещаться. Мы задаем её в четыре раза больше (по площади), чем один фон 1024x1024.
this.cameras.main.setBounds(0, 0, 1024 * 2, 1024 * 2);
Затем мы размещаем четыре фоновых изображения в виде сетки 2x2, чтобы заполнить эту большую область.
this.add.image(0, 0, 'bg').setOrigin(0);
this.add.image(1024, 0, 'bg').setOrigin(0);
this.add.image(0, 1024, 'bg').setOrigin(0);
this.add.image(1024, 1024, 'bg').setOrigin(0);
Управление с клавиатуры и начальная позиция камеры
Для управления нам понадобятся клавиши. Создаем две группы:
- `this.cursors` для стрелок (по умолчанию в Phaser).
- `this.keys` для клавиш WASD, созданные через `this.input.keyboard.addKeys`.
this.cursors = this.input.keyboard.createCursorKeys();
this.keys = this.input.keyboard.addKeys('W,A,S,D');
Важный шаг — вызов this.cameras.main.centerToBounds(). Этот метод мгновенно позиционирует камеру так, чтобы её центр находился в центре заданных границ (bounds). Это удобно для старта в середине большой игровой области.
Также создаем текстовый объект с setScrollFactor(0). Это гарантирует, что текст будет оставаться на месте относительно экрана, а не двигаться вместе с камерой.
this.text = this.add.text(32, 32).setScrollFactor(0).setFontSize(32).setColor('#ffffff');
Логика обновления: движение и вращение
Вся магия происходит в методе update. Для удобства создаем ссылку cam на основную камеру.
Сначала мы обновляем текст, выводя текущие свойства камеры: scrollX, scrollY (смещение камеры) и координаты её средней точки (midPoint).
const cam = this.cameras.main;
this.text.setText([
'ScrollX: ' + cam.scrollX,
'ScrollY: ' + cam.scrollY,
'MidX: ' + cam.midPoint.x,
'MidY: ' + cam.midPoint.y
]);
Затем обрабатываем ввод. Клавиши A и D изменяют свойство cam.scrollX, что приводит к горизонтальной прокрутке камеры. Аналогично W и S управляют cam.scrollY для вертикальной прокрутки.
if (this.keys.A.isDown)
{
cam.scrollX -= 6;
}
else if (this.keys.D.isDown)
{
cam.scrollX += 6;
}
if (this.keys.W.isDown)
{
cam.scrollY -= 6;
}
else if (this.keys.S.isDown)
{
cam.scrollY += 6;
}
Стрелки влево и вправо управляют ключевым свойством — cam.rotation. Его изменение приводит к вращению всего видового порта камеры вокруг её текущей точки обзора.
if (this.cursors.left.isDown)
{
cam.rotation -= 0.01;
}
else if (this.cursors.right.isDown)
{
cam.rotation += 0.01;
}
Конфигурация игры и запуск
Код завершается стандартной конфигурацией игры Phaser. Обратите внимание, что в config включен physics плагин Arcade, хотя в данном примере он не используется. Основная камера создается автоматически и доступна как this.cameras.main.
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
physics: {
default: 'arcade',
},
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Вращение камеры в Phaser 3 сводится к изменению одного свойства rotation у объекта камеры. Этот пример демонстрирует базовый паттерн: настройка границ, позиционирование и обработка ввода для управления scrollX, scrollY и rotation. Для экспериментов попробуйте: изменить скорость вращения, привязать вращение к движению персонажа, использовать cam.zoom вместе с вращением для создания эффекта "закручивания", или анимировать свойство rotation через Tween для плавных переходов между локациями.
