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

Создание игрового мира — это не только про отрисовку графики, но и про управление вниманием игрока. Визуальные эффекты, такие как тряска камеры, — мощный инструмент для передачи ударов, взрывов или других значимых событий, делая игру более отзывчивой и кинематографичной. В этой статье на примере простого платформера мы разберем, как в Phaser 3 реализовать управление камерой с клавиатуры и добавить эффект её тряски по клику мыши. Вы научитесь работать с `FixedKeyControl` для плавного перемещения по тайловой карте и использовать метод `shake()` для создания моментального визуального воздействия.

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


this.controls;

class Example extends Phaser.Scene
{
    constructor ()
    {
        super();
    }

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('tiles', 'assets/tilemaps/tiles/cybernoid.png');
        this.load.tilemapTiledJSON('map', 'assets/tilemaps/maps/cybernoid.json');
    }

    create ()
    {
        const map = this.make.tilemap({ key: 'map' });
        const tiles = map.addTilesetImage('cybernoid', 'tiles');
        const layer = map.createLayer(0, tiles, 0, 0);
        this.cameras.main.setBounds(0, 0, map.widthInPixels, map.heightInPixels);

        const cursors = this.input.keyboard.createCursorKeys();
        const controlConfig = {
            camera: this.cameras.main,
            left: cursors.left,
            right: cursors.right,
            up: cursors.up,
            down: cursors.down,
            speed: 0.5
        };
        this.controls = new Phaser.Cameras.Controls.FixedKeyControl(controlConfig);

        //  Every time you click, shake the camera
        this.input.on('pointerdown', function () {
            this.cameras.main.shake(500);
        }, this);
    }

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

const config = {
    type: Phaser.WEBGL,
    width: 800,
    height: 600,
    backgroundColor: '#2d2d2d',
    parent: 'phaser-example',
    pixelArt: true,
    scene: Example
};

const game = new Phaser.Game(config);

Загрузка тайловой карты

Основой нашего уровня служит тайловая карта, созданная в редакторе Tiled. В методе preload() мы загружаем два ключевых ресурса: изображение с tileset'ом и JSON-файл с картой.

this.load.image('tiles', 'assets/tilemaps/tiles/cybernoid.png');
this.load.tilemapTiledJSON('map', 'assets/tilemaps/maps/cybernoid.json');

Затем в create() создаём объект тайловой карты (Tilemap) и связываем его с загруженным изображением tileset'а, используя его внутреннее имя 'cybernoid' из JSON. Слой карты создаётся и добавляется на сцену. Чтобы камера могла перемещаться за пределами окна игры, для неё устанавливаются границы (setBounds), равные размерам карты в пикселях.

const map = this.make.tilemap({ key: 'map' });
const tiles = map.addTilesetImage('cybernoid', 'tiles');
const layer = map.createLayer(0, tiles, 0, 0);
this.cameras.main.setBounds(0, 0, map.widthInPixels, map.heightInPixels);

Управление камерой с клавиатуры

Для удобного перемещения по большой карте используется система Phaser.Cameras.Controls.FixedKeyControl. Она позволяет привязать клавиши управления к движению камеры.

Сначала получаем объект с состоянием клавиш-стрелок.

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

Затем создаём конфигурационный объект для контрола. В нём указываем целевую камеру (this.cameras.main), привязку клавиш и скорость перемещения.

const controlConfig = {
    camera: this.cameras.main,
    left: cursors.left,
    right: cursors.right,
    up: cursors.up,
    down: cursors.down,
    speed: 0.5
};
this.controls = new Phaser.Cameras.Controls.FixedKeyControl(controlConfig);

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

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

Эффект тряски камеры

Самый простой способ добавить драматизма — это тряска камеры в момент какого-либо события (выстрел, удар, взрыв). В Phaser это делается одним вызовом метода shake() у объекта камеры.

В примере мы добавляем слушатель события клика (pointerdown) на всю игровую область. Каждый клик запускает эффект тряски длительностью 500 миллисекунд.

this.input.on('pointerdown', function () {
    this.cameras.main.shake(500);
}, this);

Метод shake() принимает несколько параметров, но в базовом варианте достаточно указать длительность эффекта. Камера будет хаотично дрожать в заданных пределах, создавая ощущение удара или толчка. Обратите внимание на контекст this, переданный третьим аргументом в метод on(), чтобы внутри колбэка получить доступ к сцене и её камере.

Конфигурация игры и финальный штрих

Весь функционал объединяется в стандартной конфигурации игры Phaser. Ключевой момент для pixel-art игр — включение свойства pixelArt: true. Это отключает сглаживание текстур, сохраняя чёткие пиксельные границы.

const config = {
    type: Phaser.WEBGL,
    width: 800,
    height: 600,
    backgroundColor: '#2d2d2d',
    parent: 'phaser-example',
    pixelArt: true,
    scene: Example
};
const game = new Phaser.Game(config);

Благодаря pixelArt: true и правильно настроенным границам камеры, управление и тряска выглядят органично даже в стилизованной под ретро игре.

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

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