О чем этот пример
При разработке игр с обширными уровнями или картами часто возникает необходимость в камере, которая может следовать за игроком и одновременно масштабировать обзор. Пример bugs/6878 zoom.js демонстрирует, как в Phaser 3 настроить камеру для следования за спрайтом с сильным увеличением (зумом) в пределах огромного игрового мира. Это полезно для создания эффектов приближения, изометрических проекций или просто для детального рассмотрения действий игрока на масштабной локации. В статье мы разберем ключевые методы работы с камерой: установку границ мира, привязку к объекту, настройку "мертвой зоны" и, самое главное, управление уровнем масштабирования. Вы узнаете, как эти настройки взаимодействуют друг с другом и как их применять в своих проектах.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene {
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('ship', 'assets/sprites/phaser-ship.png');
}
create() {
this.cameras.main.setBounds(0, 0, 1024 * 4, 1024 * 4);
for (let y = 0; y < 4; y++) {
for (let x = 0; x < 4; x++) {
this.add.image(1024 * x, 1024 * y, 'bg').setOrigin(0);
}
}
this.player = this.add.image(1000, 1024, 'ship');
this.cameras.main.startFollow(this.player, false);
this.cameras.main.setDeadzone(5, 5);
this.cameras.main.setZoom(5);
this.tweens.add({
targets: this.player,
x: 1300,
yoyo: true,
duration: 300 * 200
});
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
pixelArt: true,
scene: Example
};
const game = new Phaser.Game(config);
Подготовка мира и создание фона
Перед настройкой камеры необходимо подготовить игровой мир. В данном примере создается большое пространство размером 4096x4096 пикселей (4x4 тайла по 1024 пикселя каждый). Это делается в методе create.
Сначала устанавливаются границы камеры с помощью setBounds. Это определяет область, за пределы которой камера не может выйти.
Затем в двойном цикле создается фон из повторяющихся изображений, чтобы заполнить всю эту область.
this.cameras.main.setBounds(0, 0, 1024 * 4, 1024 * 4);
for (let y = 0; y < 4; y++) {
for (let x = 0; x < 4; x++) {
this.add.image(1024 * x, 1024 * y, 'bg').setOrigin(0);
}
}
Здесь важно свойство .setOrigin(0), которое устанавливает точку привязки изображения в его левый верхний угол. Это позволяет корректно выстраивать тайлы без зазоров.
Создание игрока и настройка следования камеры
Далее создается спрайт игрока (корабля) и помещается в определенную точку мира.
this.player = this.add.image(1000, 1024, 'ship');
Затем камера "привязывается" к этому спрайту с помощью метода startFollow. Второй параметр false отключает линейную интерполяцию (LERP), что заставляет камеру следовать за целью мгновенно, без плавного "догоняющего" эффекта.
this.cameras.main.startFollow(this.player, false);
Теперь центр камеры будет совпадать с позицией спрайта player.
Мертвая зона и увеличение (Zoom)
Ключевые настройки для создания стабильного и приятного визуального эффекта — это "мертвая зона" (Deadzone) и масштаб (Zoom).
Мертвая зона — это область в центре камеры, внутри которой движение цели не вызывает перемещения самой камеры. Это предотвращает тряску при малейших колебаниях позиции игрока.
this.cameras.main.setDeadzone(5, 5);
В примере установлена очень маленькая зона 5x5 пикселей, что означает, что камера начнет двигаться, как только игрок отклонится от ее центра более чем на 2.5 пикселя.
Самый эффектный метод — setZoom. Он задает уровень масштабирования камеры.
this.cameras.main.setZoom(5);
Значение `5` означает пятикратное увеличение. Все содержимое камеры (игровой мир) будет отображаться в 5 раз крупнее. Важно помнить, что при таком зуме видимая область камеры (viewport) резко уменьшается, и "мертвая зона" в 5 пикселей на экране соответствует уже 1 пикселю в игровом мире (5 / 5 = 1).
Анимация движения для демонстрации
Чтобы продемонстрировать работу камеры в действии, к спрайту игрока применяется простая твин-анимация.
this.tweens.add({
targets: this.player,
x: 1300,
yoyo: true,
duration: 300 * 200
});
Анимация плавно перемещает корабль по оси X из начальной точки 1000 в точку 1300, а затем обратно (благодаря параметру yoyo: true). Очень длинная duration (60000 мс) обеспечивает медленное, заметное движение, идеальное для наблюдения за поведением камеры с зумом.
В результате мы видим, как камера, увеличенная в 5 раз, с небольшой "мертвой зоной", плавно следует за медленно двигающимся кораблем по огромному миру, создавая эффект детального наблюдения.
Что попробовать дальше
Пример наглядно показывает мощь и гибкость системы камер Phaser 3. Комбинация setBounds, startFollow, setDeadzone и setZoom позволяет легко реализовать сложное поведение камеры, необходимое для множества жанров игр.
Для экспериментов попробуйте изменить значение в setZoom на 0.5 (уменьшение), 1 (нормальный вид) или 10 (сильное увеличение). Поиграйте с размерами setDeadzone — увеличьте их до 100x100, чтобы камера двигалась только при значительном смещении игрока. Также можно включить интерполяцию в startFollow, установив второй параметр в true, и посмотреть, как изменится "ощущение" от управления.
