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

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

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    arrow;

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

    create ()
    {
        this.arrow = this.physics.add.image(400, 100, 'arrow')
            .setVelocity(200, 0)
            .setBounce(1, 1)
            .setCollideWorldBounds(true);
    }

    update ()
    {
        this.arrow.rotation = this.arrow.body.angle;
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'phaser-example',
    physics: {
        default: 'arcade',
        arcade: {
            debug: false,
            gravity: { y: 600 }
        }
    },
    scene: Example
};

const game = new Phaser.Game(config);

Настройка сцены и загрузка ассетов

Класс Example расширяет Phaser.Scene. В методе preload мы загружаем спрайт стрелки из удаленного репозитория.

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

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

Создание физического тела и задание движения

В методе create мы создаем спрайт стрелки как физический объект Arcade Physics.

this.arrow = this.physics.add.image(400, 100, 'arrow')
    .setVelocity(200, 0)
    .setBounce(1, 1)
    .setCollideWorldBounds(true);

* this.physics.add.image создает объект Image с физическим телом Arcade Physics. * setVelocity(200, 0) сразу задает начальную горизонтальную скорость (200 пикселей в секунду). * setBounce(1, 1) делает отскок от границ абсолютно упругим (коэффициент 1). * setCollideWorldBounds(true) включает столкновение с границами игрового мира.

Важно: тело body у объекта появляется именно благодаря использованию this.physics.add.image.

Связывание вращения спрайта с углом скорости

Магия происходит в методе update, который вызывается на каждом кадре игры.

this.arrow.rotation = this.arrow.body.angle;

* this.arrow.body.angle — это свойство физического тела, которое автоматически вычисляет угол (в радианах) вектора текущей скорости (body.velocity). * Присваивая это значение свойству rotation спрайта, мы заставляем его графику непрерывно поворачиваться в сторону движения.

Таким образом, когда стрелка отскакивает от стен и меняет вектор скорости, ее изображение мгновенно разворачивается по новому направлению.

Конфигурация игры и физики

Вся сцена инициализируется в объекте конфигурации.

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'phaser-example',
    physics: {
        default: 'arcade',
        arcade: {
            debug: false,
            gravity: { y: 600 }
        }
    },
    scene: Example
};

Обратите внимание на раздел physics. Здесь активируется система arcade и задается гравитация по оси Y. Несмотря на то что в данном примере стрелка движется горизонтально, гравитация влияет на ее поведение при отскоках.

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

Использование sprite.body.angle для управления rotation — это канонический и производительный способ синхронизации визуального представления объекта с его физическим движением в Phaser 3. Для экспериментов попробуйте: 1. Изменить начальную скорость через setVelocity, чтобы увидеть, как угол вычисляется для разных векторов. 2. Применить эту технику к группе снарядов (physics.add.group). 3. Добавить управление с клавиатуры и убедиться, что спрайт игрока всегда смотрит в сторону последнего движения.