О чем этот пример
Плавное перемещение камеры — ключевой элемент для создания динамичных игр с большим миром. Вместо резких скачков, которые могут дезориентировать игрока, можно создать эффект путешествия по локации. Эта статья покажет, как использовать метод `pan()` для анимированного перемещения камеры между точками с различными эффектами плавности (easing). Вы научитесь управлять вниманием игрока, подчеркивать важные объекты и создавать кинематографичные переходы между сценами или событиями в игре.
Версия 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('map', 'assets/tests/camera/earthbound-scarab.png');
}
create ()
{
this.cameras.main.setBounds(0, 0, 1024, 2048);
this.add.image(0, 0, 'map').setOrigin(0);
this.cameras.main.setZoom(4);
this.cameras.main.centerOn(0, 0);
console.log(this.cameras.main.getScroll(767, 1096));
this.text = this.add.text(304, 230).setText('Click to move').setScrollFactor(0);
this.text.setShadow(1, 1, '#000000', 2);
let pos = 0;
this.input.on('pointerdown', function () {
const cam = this.cameras.main;
if (pos === 0)
{
cam.pan(767, 1096, 2000, 'Power2');
pos++;
}
else if (pos === 1)
{
cam.pan(703, 1621, 2000, 'Elastic');
pos++;
}
else if (pos === 2)
{
cam.pan(256, 623, 2000, 'Sine.easeInOut');
pos++;
}
else if (pos === 3)
{
cam.pan(166, 304, 2000);
pos++;
}
else if (pos === 4)
{
cam.pan(624, 158, 2000);
pos++;
}
else if (pos === 5)
{
cam.pan(680, 330, 2000);
pos++;
}
else if (pos === 6)
{
cam.pan(748, 488, 2000);
pos++;
}
else if (pos === 7)
{
cam.pan(1003, 1719, 2000);
pos = 0;
}
}, this);
}
update ()
{
const cam = this.cameras.main;
this.text.setText(['Click to move', 'x: ' + cam.scrollX, 'y: ' + cam.scrollY ]);
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
pixelArt: true,
physics: {
default: 'arcade',
},
scene: Example
};
const game = new Phaser.Game(config);
Настройка мира и камеры
Перед началом работы с анимацией камеры необходимо правильно подготовить сцену. В первую очередь задаются границы игрового мира, за которые камера не сможет выйти. Это важно, чтобы при панорамировании мы не увидели пустые области за пределами контента.
Затем мы добавляем фоновое изображение-карту и настраиваем начальное состояние основной камеры. Увеличение (setZoom) помогает сфокусироваться на конкретной стартовой области.
this.cameras.main.setBounds(0, 0, 1024, 2048);
this.add.image(0, 0, 'map').setOrigin(0);
this.cameras.main.setZoom(4);
this.cameras.main.centerOn(0, 0);
Как работает метод pan()
Метод pan() объекта камеры — это основное средство для плавного перемещения. Он анимирует изменение свойств scrollX и scrollY, отвечающих за положение камеры в мире.
Метод принимает несколько аргументов: - **x, y**: Целевые координаты в мировом пространстве, к которым нужно переместить центр камеры. - **duration**: Длительность анимации в миллисекундах. - **ease**: Необязательный параметр. Строка с названием функции плавности (easing function), которая определяет характер движения (линейный, упругий, с ускорением и т.д.). Если не указан, используется линейная интерполяция ('Linear').
Вот пример вызова с разными функциями плавности:
// Плавное движение с функцией 'Power2'
cam.pan(767, 1096, 2000, 'Power2');
// Упругое движение с отскоком в конце ('Elastic')
cam.pan(703, 1621, 2000, 'Elastic');
// Движение с плавным ускорением и замедлением ('Sine.easeInOut')
cam.pan(256, 623, 2000, 'Sine.easeInOut');
Организация интерактивного перехода
В примере переходы между точками активируются по клику мыши. Для этого используется слушатель события pointerdown. Состояние, определяющее, к какой точке двигаться дальше, хранится в переменной pos. Этот простой конечный автомат последовательно перебирает заранее заданные координаты.
Текст с координатами камеры (scrollX, scrollY) обновляется в методе update() каждый кадр, что дает игроку визуальную обратную связь. Важно отметить, что сам текст имеет setScrollFactor(0), что делает его статичным относительно экрана, а не мира.
this.input.on('pointerdown', function () {
const cam = this.cameras.main;
if (pos === 0) {
cam.pan(767, 1096, 2000, 'Power2');
pos++;
}
// ... другие условия
}, this);
Функции плавности (Easing)
Phaser использует систему функций плавности из библиотеки Tween. Эти функции определяют, как значение изменяется от начального к конечному за заданное время. Выбор функции сильно влияет на ощущения от анимации.
- **'Linear'**: Равномерное движение без ускорения. - **'Power2' (и другие 'PowerN')**: Движение с ускорением. Число указывает на степень кривой. - **'Elastic'**: Создает эффект упругости с несколькими колебаниями в конце. - **'Sine.easeInOut'**: Плавное начало и плавный конец, выглядит очень естественно.
Полный список доступных функций можно найти в документации Phaser по Tween. Используйте разные варианты, чтобы передать нужное настроение: 'Elastic' для комичных или "пружинистых" действий, 'Sine.easeInOut' для плавных и спокойных переходов.
Что попробовать дальше
Метод cameras.main.pan() — это мощный и простой инструмент для создания управляемых переходов камеры. Он оживляет игровой мир, направляет внимание игрока и добавляет игре полировки. Для экспериментов попробуйте:
1. Связать панорамирование не с кликом, а с достижением игроком определенной точки на карте.
2. Использовать событие camera.on('camerapancomplete', callback) для запуска диалога или следующего действия после завершения движения.
3. Комбинировать pan() с методами zoom() и rotate() для создания сложных кинематографичных кадров.
