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

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

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    player;
    cursors;

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('block', 'assets/sprites/block.png');
    }

    create ()
    {
        this.cursors = this.input.keyboard.createCursorKeys();

        this.player = this.physics.add.image(400, 300, 'block');

        this.player.setCollideWorldBounds(true);
    }

    update ()
    {
        this.player.setVelocity(0);

        if (this.cursors.left.isDown)
        {
            this.player.setVelocityX(-300);
        }
        else if (this.cursors.right.isDown)
        {
            this.player.setVelocityX(300);
        }

        if (this.cursors.up.isDown)
        {
            this.player.setVelocityY(-300);
        }
        else if (this.cursors.down.isDown)
        {
            this.player.setVelocityY(300);
        }
    }
}

const config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    backgroundColor: '#0072bc',
    physics: {
        default: 'arcade',
        arcade: {
            debug: true
        }
    },
    scene: Example
};

const game = new Phaser.Game(config);

Инициализация управления и создание спрайта

Вся логика примера содержится внутри класса сцены Example. Управление создается и настраивается в методе create(), который выполняется один раз при старте сцены.

Сначала мы получаем доступ к курсорным клавишам (стрелкам) через менеджер ввода Phaser. Это стандартный способ для быстрого доступа к основным клавишам направления.

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

Затем создается физический спрайт — игровой объект, с которым связан Arcade Physics. Мы помещаем его в центр экрана (координаты 400x300) и указываем ключ загруженного изображения.

this.player = this.physics.add.image(400, 300, 'block');
this.player.setCollideWorldBounds(true);

Метод setCollideWorldBounds(true) — это важный вызов физического движка. Он гарантирует, что спрайт не сможет вылететь за границы игрового мира, что критически важно для большинства игр.

Логика движения в методе update

Основная логика перемещения находится в методе update(), который вызывается на каждом кадре игры. Это идеальное место для обработки ввода и изменения состояния объектов.

Первым делом мы сбрасываем скорость спрайта до нуля по обеим осям. Это необходимо, чтобы движение прекращалось, когда игрок отпускает клавиши. Без этого сброса спрайт продолжал бы двигаться с последней заданной скоростью.

this.player.setVelocity(0);

Далее мы проверяем состояние каждой курсорной клавиши. Объект this.cursors содержит свойства left, right, up, down, каждое из которых является объектом Key. Его метод isDown возвращает true, если клавиша нажата в данный момент.

if (this.cursors.left.isDown)
{
    this.player.setVelocityX(-300);
}
else if (this.cursors.right.isDown)
{
    this.player.setVelocityX(300);
}

Аналогичная логика применяется для вертикального движения. Обратите внимание, что используется метод setVelocityX и setVelocityY. Это методы Arcade Physics, которые напрямую задают линейную скорость тела, создавая мгновенное, "коробочное" движение, характерное для многих аркадных игр.

Настройка физики и запуск игры

Конфигурация игры определяет ее базовые параметры. Ключевой раздел здесь — physics, который активирует Arcade Physics и включает режим отладки.

const config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    backgroundColor: '#0072bc',
    physics: {
        default: 'arcade',
        arcade: {
            debug: true
        }
    },
    scene: Example
};

Параметр debug: true включает отладочную визуализацию для всех физических тел. На экране вокруг спрайта block вы увидите зеленый контур — это границы физического тела (хитбокс), которое рассчитывает столкновения. Это невидимая область, которая может отличаться от графического спрайта.

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

const game = new Phaser.Game(config);

Почему именно такая структура кода?

Пример демонстрирует каноничную, чистую архитектуру Phaser 3, разделяя код по методам жизненного цикла сцены.

* **preload()**: Здесь загружаются ассеты (изображения, звуки). Это гарантирует, что к моменту создания объектов они уже будут в памяти. * **create()**: Здесь происходит однократная инициализация объектов сцены, создание физических тел, настройка управления и игровой логики. Вызов createCursorKeys() помещают сюда, так как создавать слушатели ввода многократно в update() — ошибка. * **update()**: Сюда помещается код, который должен выполняться непрерывно — проверка ввода, пересчет скоростей, проверка условий победы. Именно поэтому проверка isDown и вызов setVelocity находятся здесь.

Такое разделение делает код предсказуемым, удобным для отладки и масштабирования. Например, вы можете легко добавить в create() создание врагов или препятствий, а логику их взаимодействия с игроком перенести в update().

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

Вы разобрали базовый, но мощный паттерн управления в Phaser 3. Он использует встроенный менеджер ввода для клавиатуры и физический движок Arcade для перемещения объектов. Для экспериментов попробуйте: изменить значение скорости (300) на большее или меньшее; добавить ускорение вместо мгновенной скорости; привязать управление к клавишам WASD, используя this.input.keyboard.addKeys(); или добавить второй спрайт, управляемый другим набором клавиш, для создания локального мультиплеера.