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

Динамичное управление камерой — ключевой элемент для создания исследовательских игр, стратегий или платформеров с большими уровнями. Встроенный в Phaser класс `SmoothedKeyControl` позволяет легко реализовать интуитивное перемещение камеры с клавиатуры, с плавным ускорением и инерцией. Эта статья покажет, как настроить такое управление и подключить визуальный дебаг-интерфейс для отслеживания параметров камеры в реальном времени.

Версия 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('grid', 'assets/pics/uv-grid-diag.png');
    }

    create () 
    {
        //  The grid image is 1024 x 1024, let's draw 4 of them (2 by 2)
        this.add.image(0, 0, 'grid').setOrigin(0);
        this.add.image(1024, 0, 'grid').setOrigin(0);
        this.add.image(0, 1024, 'grid').setOrigin(0);
        this.add.image(1024, 1024, 'grid').setOrigin(0);

        const cursors = this.input.keyboard.createCursorKeys();

        const controlConfig = {
            camera: this.cameras.main,
            left: cursors.left,
            right: cursors.right,
            up: cursors.up,
            down: cursors.down,
            zoomIn: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Q),
            zoomOut: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.E),
            acceleration: 0.06,
            drag: 0.0005,
            maxSpeed: 1.0
        };

        this.controls = new Phaser.Cameras.Controls.SmoothedKeyControl(controlConfig);

        const cam = this.cameras.main;

        const gui = new dat.GUI();

        const help = {
            line1: 'Cursors to move',
            line2: 'Q & E to zoom'
        }

        const f1 = gui.addFolder('Camera');
        f1.add(cam, 'x').listen();
        f1.add(cam, 'y').listen();
        f1.add(cam, 'scrollX').listen();
        f1.add(cam, 'scrollY').listen();
        f1.add(cam, 'rotation').min(0).step(0.01).listen();
        f1.add(cam, 'zoom', 0.1, 2).step(0.1).listen();
        f1.add(help, 'line1');
        f1.add(help, 'line2');
        f1.open();
    }

    update (time, delta) 
    {
        this.controls.update(delta);
    }
}

const config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    backgroundColor: '#000000',
    scene: Example
};

const game = new Phaser.Game(config);

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

В методе preload мы загружаем одно изображение, которое будет служить текстурой фона. Для создания большой области, которую можно исследовать с помощью камеры, мы разместим это изображение несколько раз в методе create.

preload () 
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('grid', 'assets/pics/uv-grid-diag.png');
}

После загрузки изображение 'grid' добавляется на сцену четыре раза, формируя квадрат 2x2. Установка setOrigin(0) означает, что точка привязки изображения — его левый верхний угол (координаты 0,0). Это позволяет легко выстраивать тайлы без нахлестов.

this.add.image(0, 0, 'grid').setOrigin(0);
this.add.image(1024, 0, 'grid').setOrigin(0);
this.add.image(0, 1024, 'grid').setOrigin(0);
this.add.image(1024, 1024, 'grid').setOrigin(0);

Настройка клавиш управления

Для управления камерой с клавиатуры нам нужны объекты, отслеживающие состояние клавиш. Phaser предоставляет удобные методы для этого.

Сначала получаем стандартные стрелки курсора.

const cursors = this.input.keyboard.createCursorKeys();

Затем создаем отдельные объекты клавиш для зума. В данном примере для увеличения и уменьшения масштаба используются клавиши `QиE. Мы используем методthis.input.keyboard.addKey, передавая ему код нужной клавиши из перечисленияPhaser.Input.Keyboard.KeyCodes`.

zoomIn: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Q),
zoomOut: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.E)

Создание контроллера плавной камеры

Основная магия происходит в объекте controlConfig и при создании экземпляра SmoothedKeyControl. Этот класс реализует управление камерой с физикой: плавный разгон и замедление.

const controlConfig = {
    camera: this.cameras.main,
    left: cursors.left,
    right: cursors.right,
    up: cursors.up,
    down: cursors.down,
    zoomIn: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Q),
    zoomOut: this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.E),
    acceleration: 0.06,
    drag: 0.0005,
    maxSpeed: 1.0
};

this.controls = new Phaser.Cameras.Controls.SmoothedKeyControl(controlConfig);

* camera: Основная камера сцены, которой будем управлять. * acceleration: Значение ускорения. Чем оно выше, тем быстрее камера набирает скорость при зажатой клавише. * drag: Коэффициент сопротивления (инерции). Определяет, как быстро камера остановится после отпускания клавиш. * maxSpeed: Максимально допустимая скорость перемещения камеры.

Чтобы система управления работала, необходимо вызывать метод update контроллера каждый кадр в основном игровом цикле.

update (time, delta) 
{
    this.controls.update(delta);
}

Параметр delta (время, прошедшее с прошлого кадра) передается в метод update контроллера, чтобы движение оставалось плавным и независимым от частоты кадров.

Визуализация параметров камеры с dat.GUI

Для отладки и понимания работы камеры крайне полезно видеть ее числовые параметры в реальном времени. В примере для этого используется библиотека dat.GUI.

Сначала создается ссылка на основную камеру и экземпляр GUI.

const cam = this.cameras.main;
const gui = new dat.GUI();

Затем создается папка (folder) в интерфейсе и добавляются контролы для отслеживания (listen) свойств камеры.

const f1 = gui.addFolder('Camera');
f1.add(cam, 'x').listen();
f1.add(cam, 'y').listen();
f1.add(cam, 'scrollX').listen();
f1.add(cam, 'scrollY').listen();
f1.add(cam, 'rotation').min(0).step(0.01).listen();
f1.add(cam, 'zoom', 0.1, 2).step(0.1).listen();

* `x,y`: Мировые координаты центра камеры. * scrollX, scrollY: Смещение (скролл) камеры. Именно эти свойства напрямую меняет SmoothedKeyControl. * rotation: Вращение камеры в радианах. * zoom: Масштаб камеры. Метод .listen() заставляет значения в интерфейсе автоматически обновляться при их изменении в коде.

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

Класс SmoothedKeyControl — это мощный и простой инструмент для добавления профессионального управления камерой в вашу игру. Вы можете экспериментировать с параметрами acceleration, drag и maxSpeed, чтобы добиться разного "ощущения" движения — от тяжелой камеры в стратегии до быстрой и отзывчивой в экшн-игре. Попробуйте привязать управление не к стрелкам, а к клавишам WASD, добавить поддержку геймпада через this.input.gamepad или реализовать перемещение камеры при движении курсора к краю экрана (RTS-стиль).