О чем этот пример
Управление камерой — ключевой навык для создания динамичных и захватывающих игр. Phaser предоставляет мощный API для камер, позволяя не просто следить за игроком, но и создавать кинематографичные переходы, эффекты внимания и плавную навигацию по большим мирам. В этой статье мы разберем практический пример, где камера меняет прозрачность (альфа-канал), панорамирует к заданным точкам и плавно изменяет масштаб по клику мыши. Вы научитесь комбинировать эти методы для создания сложных визуальных последовательностей, таких как провалы в воспоминания, переходы между локациями или драматические акценты.
Версия 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(1);
this.cameras.main.centerOn(0, 0);
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.alpha = 0.5;
cam.pan(767, 1096, 2000, 'Power2');
cam.zoomTo(4, 3000);
pos++;
}
else if (pos === 1)
{
cam.alpha = 1;
cam.pan(703, 1621, 2000, 'Elastic');
cam.zoomTo(2, 3000);
pos++;
}
else if (pos === 2)
{
cam.alpha = 0.2;
cam.pan(256, 623, 2000, 'Sine.easeInOut');
cam.zoomTo(1, 3000);
pos++;
}
else if (pos === 3)
{
cam.alpha = 0.9;
cam.pan(166, 304, 2000);
cam.zoomTo(4, 1500);
pos++;
}
else if (pos === 4)
{
cam.alpha = 0.1;
cam.pan(624, 158, 2000);
cam.zoomTo(0.5, 3000);
pos++;
}
else if (pos === 5)
{
cam.alpha = 0.6;
cam.pan(680, 330, 2000);
pos++;
}
else if (pos === 6)
{
cam.alpha = 1;
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);
Настройка сцены и загрузка
В методе preload загружается изображение большой карты, которое будет служить игровым миром. Важно задать корректный базовый URL для загрузчика.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('map', 'assets/tests/camera/earthbound-scarab.png');
}
В create мы выполняем первоначальную настройку. Сначала устанавливаем границы (setBounds) для основной камеры this.cameras.main. Это определяет область мира, которую камера может просматривать. Затем изображение карты добавляется в начало координат мира (0,0).
create ()
{
this.cameras.main.setBounds(0, 0, 1024, 2048);
this.add.image(0, 0, 'map').setOrigin(0);
this.cameras.main.setZoom(1);
this.cameras.main.centerOn(0, 0);
// ... создание текста и обработчика клика
}
Отслеживание кликов и управление состоянием
Для переключения между разными эффектами используется простая переменная-счетчик pos. Обработчик события pointerdown на игровом поле (this.input) содержит логику, которая выполняется при каждом клике.
let pos = 0;
this.input.on('pointerdown', function () {
const cam = this.cameras.main;
// Логика в зависимости от значения pos
}, this);
Каждый клик увеличивает pos (кроме последнего случая, где счетчик сбрасывается), что позволяет циклически проходить через заранее заданную последовательность действий камеры. Переменная cam — это локальная ссылка на основную камеру для удобства.
Магия камеры: Прозрачность, панорамирование и зум
Внутри обработчика для каждого значения pos выполняется уникальная комбинация методов камеры. Это сердце примера, демонстрирующее три основных эффекта.
* **Прозрачность (Alpha)**: Свойству cam.alpha присваивается значение от 0 (полная прозрачность) до 1 (полная непрозрачность). Это позволяет создавать эффекты затухания.
* **Панорамирование (Pan)**: Метод cam.pan(x, y, duration, ease) плавно перемещает центр камеры к заданным мировым координатам за указанное время (в миллисекундах). Необязательный параметр ease задает функцию плавности анимации (например, 'Power2', 'Elastic').
* **Приближение/Отдаление (ZoomTo)**: Метод cam.zoomTo(zoomLevel, duration) анимирует изменение масштаба камеры.
// Пример первого перехода
if (pos === 0)
{
cam.alpha = 0.5; // Полупрозрачность
cam.pan(767, 1096, 2000, 'Power2'); // Плавное движение к точке (767,1096)
cam.zoomTo(4, 3000); // Увеличить масштаб в 4 раза
pos++;
}
Каждый блок кода меняет эти параметры по-разному, создавая разнообразные визуальные переходы. Обратите внимание, как меняется ease-функция, влияя на характер движения.
Динамический UI с текстом
Чтобы визуализировать текущее положение камеры, в сцене создается текстовый объект. Ключевой момент — вызов .setScrollFactor(0). Это фиксирует текст относительно экрана, а не игрового мира, поэтому он не двигается вместе с камерой.
this.text = this.add.text(304, 230)
.setText('Click to move')
.setScrollFactor(0); // Текст привязан к экрану
this.text.setShadow(1, 1, '#000000', 2);
В методе update, который вызывается каждый кадр, текст обновляется, отображая текущие координаты прокрутки камеры (cam.scrollX и cam.scrollY). Это полезно для отладки и понимания логики работы камеры.
update ()
{
const cam = this.cameras.main;
this.text.setText(['Click to move', 'x: ' + cam.scrollX, 'y: ' + cam.scrollY ]);
}
Конфигурация игры
Код завершается стандартной конфигурацией экземпляра игры Phaser.Game. Важная настройка здесь — pixelArt: true, которая включает фильтрацию текстур для пиксель-арта, предотвращая размытие при масштабировании.
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);
Что попробовать дальше
Этот пример — отличная отправная точка для освоения выразительных возможностей камеры в Phaser. Комбинируя alpha, pan и zoomTo, вы можете создавать сложные сцены без необходимости анимировать сами игровые объекты. Для экспериментов попробуйте: изменить последовательность и параметры переходов; привязать эффекты не к клику, а к событиям игры (например, получению урона или открытию сундука); использовать несколько камер (this.cameras.add) с разными свойствами и переключаться между ними для эффекта разделенного экрана или картины в картине.
