О чем этот пример

Динамическое управление камерой — ключ к созданию захватывающих игровых миров. Плавные переходы между локациями и изменение масштаба не только улучшают визуальное восприятие, но и направляют внимание игрока. В этой статье мы разберем, как использовать методы `zoomTo` и `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(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.pan(767, 1096, 2000, 'Power2');
                cam.zoomTo(4, 3000);
                pos++;
            }
            else if (pos === 1)
            {
                cam.pan(703, 1621, 2000, 'Elastic');
                cam.zoomTo(2, 3000);
                pos++;
            }
            else if (pos === 2)
            {
                cam.pan(256, 623, 2000, 'Sine.easeInOut');
                cam.zoomTo(1, 3000);
                pos++;
            }
            else if (pos === 3)
            {
                cam.pan(166, 304, 2000);
                cam.zoomTo(4, 1500);
                pos++;
            }
            else if (pos === 4)
            {
                cam.pan(624, 158, 2000);
                cam.zoomTo(0.5, 3000);
                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);

Подготовка сцены и загрузка карты

Первым делом в методе preload загружается изображение карты. Важно использовать setBaseURL, чтобы указать базовый путь к ресурсам.

В методе create происходит основная настройка. Камера получает границы (setBounds), соответствующие размеру карты, что ограничивает её перемещение. Изображение карты добавляется в начало координат (0,0) с помощью setOrigin(0). Исходный зум камеры устанавливается в 1 (100%), и она центрируется в начале координат.

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) выполняется цепочка условий if/else if, которая определяет, какую точку посетить следующей.

let pos = 0;
this.input.on('pointerdown', function () {
    const cam = this.cameras.main;
    if (pos === 0) {
        // Первый переход
        cam.pan(767, 1096, 2000, 'Power2');
        cam.zoomTo(4, 3000);
        pos++;
    }
    // ... остальные условия
}, this);

Каждый переход состоит из двух операций: панорамирования (pan) и изменения зума (zoomTo). Оба метода могут принимать время анимации в миллисекундах и строку с названием функции плавности (easing).

Методы pan и zoomTo в деталях

Метод cam.pan(x, y, duration, ease, force, callback) плавно перемещает камеру к указанным координатам scrollX и scrollY.

Метод cam.zoomTo(zoom, duration) плавно изменяет масштаб камеры до заданного значения. Зум, равный 1, соответствует исходному размеру, 2 — увеличению в два раза, 0.5 — уменьшению вдвое.

// Переместить камеру к координатам (767, 1096) за 2 секунды с плавностью 'Power2'
cam.pan(767, 1096, 2000, 'Power2');
// Увеличить масштаб камеры до 4x за 3 секунды
cam.zoomTo(4, 3000);

Функции плавности (например, 'Elastic', 'Sine.easeInOut') контролируют ускорение анимации, делая перемещения более естественными. Если ease не указан, используется линейная интерполяция.

Отображение позиции камеры в реальном времени

Чтобы визуализировать текущее положение камеры, в методе update текст на экране обновляется каждый кадр. Свойства cam.scrollX и cam.scrollY возвращают текущие координаты камеры.

update ()
{
    const cam = this.cameras.main;
    this.text.setText(['Click to move', 'x: ' + cam.scrollX, 'y: ' + cam.scrollY ]);
}

Текст создаётся в create с параметром setScrollFactor(0), что делает его неподвижным относительно экрана, а не игрового мира.

Конфигурация игры и важные настройки

Ключевая настройка для корректного отображения пиксельной графики — pixelArt: true. Она отключает сглаживание текстур. Также в конфиге определяется основной класс сцены Example.

const config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    pixelArt: true, // Важно для pixel-art игр
    physics: {
        default: 'arcade',
    },
    scene: Example // Наша сцена
};
const game = new Phaser.Game(config);

Что попробовать дальше

Методы pan и zoomTo — мощный инструмент для создания навигации по большим игровым мирам, кат-сцен или динамических эффектов. Для экспериментов попробуйте

  1. Связать перемещение камеры с движением игрока, плавно следуя за ним с небольшим отставанием
  2. Создать систему кат-сцен, запрограммировав последовательность pan и zoomTo по таймеру
  3. Использовать разные функции плавности из пакета Phaser (например, 'Bounce', 'Back') для придания анимациям уникального характера