О чем этот пример
Работа с угловым движением — ключевой навык для создания динамичных и отзывчивых игр. Phaser Arcade Physics предоставляет простой, но мощный API для управления вращением объектов. Эта статья на практическом примере покажет, как использовать угловое ускорение (`angularAcceleration`), сопротивление (`angularDrag`) и скорость (`angularVelocity`) для создания интуитивного управления вращением спрайта. Вы научитесь рассчитывать угол поворота за кадр и визуализировать физические параметры на экране.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
cursors;
graphics;
text;
wheel;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('wheel', 'assets/sprites/blade.png');
}
create ()
{
this.wheel = this.physics.add.image(400, 300, 'wheel')
.setAngularDrag(0)
.setAngularVelocity(360);
this.graphics = this.add.graphics({ fillStyle: { color: 0xffff00, alpha: 0.5 } });
this.text = this.add.text(0, 0, '', {
fixedWidth: 350,
fixedHeight: 150,
fill: 'aqua',
backgroundColor: '#000c'
});
this.cursors = this.input.keyboard.createCursorKeys();
}
update ()
{
const { left, right, down } = this.cursors;
this.wheel.setAngularAcceleration(0).setAngularDrag(0);
if (left.isDown)
{
this.wheel.setAngularAcceleration(-360);
}
else if (right.isDown)
{
this.wheel.setAngularAcceleration(360);
}
if (down.isDown)
{
this.wheel.setAngularDrag(360);
}
const deltaZ = this.wheel.body.deltaZ();
this.graphics
.clear()
.slice(
this.wheel.x,
this.wheel.y,
0.5 * this.wheel.width,
0,
Phaser.Math.DegToRad(deltaZ),
deltaZ < 0
)
.fillPath();
const { angularAcceleration, angularDrag, angularVelocity } = this.wheel.body;
this.text.setText(`
Accelerate with LEFT and RIGHT keys.
Drag with DOWN key.
Angular Acceleration: ${angularAcceleration.toFixed(1)} deg/s²
Angular Drag: ${angularDrag.toFixed(1)} deg/s²
Angular Velocity: ${angularVelocity.toFixed(1)} deg/s
Delta Z: ${deltaZ.toFixed(1)} deg/step`
);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'phaser-example',
physics: {
default: 'arcade',
arcade: { debug: false }
},
scene: Example
};
const game = new Phaser.Game(config);
Инициализация сцены и загрузка ресурсов
Класс сцены наследуется от Phaser.Scene. В методе preload() загружается единственный спрайт — изображение лезвия, которое будет выступать в роли вращающегося колеса. Базовый URL задаётся для удобства загрузки из репозитория с примерами.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('wheel', 'assets/sprites/blade.png');
}
Создание физического тела и элементов интерфейса
В методе create() происходит основная настройка. Спрайт 'wheel' добавляется в физический мир через this.physics.add.image. Это автоматически создаёт для него Arcade Physics тело.
Ключевой момент — сразу после создания задаются начальные физические свойства: угловое сопротивление (angularDrag) обнуляется, а угловая скорость (angularVelocity) устанавливается в 360 градусов в секунду. Это заставляет колесо вращаться сразу после старта сцены.
Также создаются графический объект graphics для визуализации и текстовое поле text для вывода статистики.
create ()
{
this.wheel = this.physics.add.image(400, 300, 'wheel')
.setAngularDrag(0)
.setAngularVelocity(360);
this.graphics = this.add.graphics({ fillStyle: { color: 0xffff00, alpha: 0.5 } });
this.text = this.add.text(0, 0, '', {
fixedWidth: 350,
fixedHeight: 150,
fill: 'aqua',
backgroundColor: '#000c'
});
this.cursors = this.input.keyboard.createCursorKeys();
}
Обработка ввода и применение физических сил
Метод update() вызывается каждый кадр. В нём сбрасываются угловое ускорение и сопротивление тела до нуля. Это важно делать на каждом кадре, потому что логика управления задаёт эти значения условно, только при нажатых клавишах. Без сброса ускорение или сопротивление, применённые в предыдущем кадре, остались бы активными.
Затем проверяется состояние клавиш-стрелок. Стрелки ВЛЕВО и ВПРАВО задают отрицательное и положительное угловое ускорение соответственно. Стрелка ВНИЗ включает угловое сопротивление (angularDrag), которое замедляет вращение.
update ()
{
const { left, right, down } = this.cursors;
this.wheel.setAngularAcceleration(0).setAngularDrag(0);
if (left.isDown)
{
this.wheel.setAngularAcceleration(-360);
}
else if (right.isDown)
{
this.wheel.setAngularAcceleration(360);
}
if (down.isDown)
{
this.wheel.setAngularDrag(360);
}
Визуализация и вывод отладочной информации
Одна из самых полезных функций для работы с вращением — deltaZ(). Она возвращает изменение угла поворота тела (в градусах) за последний шаг физического расчета. Это значение используется для отрисовки сектора (slice) с помощью Graphics API, который наглядно показывает, насколько и в какую сторону повернулось тело за кадр.
В текстовом блоке выводятся текущие физические параметры тела, полученные напрямую из this.wheel.body. Это отличный способ отладки и демонстрации работы физики.
const deltaZ = this.wheel.body.deltaZ();
this.graphics
.clear()
.slice(
this.wheel.x,
this.wheel.y,
0.5 * this.wheel.width,
0,
Phaser.Math.DegToRad(deltaZ),
deltaZ < 0
)
.fillPath();
const { angularAcceleration, angularDrag, angularVelocity } = this.wheel.body;
this.text.setText(`
Accelerate with LEFT and RIGHT keys.
Drag with DOWN key.
Angular Acceleration: ${angularAcceleration.toFixed(1)} deg/s²
Angular Drag: ${angularDrag.toFixed(1)} deg/s²
Angular Velocity: ${angularVelocity.toFixed(1)} deg/s
Delta Z: ${deltaZ.toFixed(1)} deg/step`
);
}
Конфигурация игры и запуск
Объект конфигурации определяет основные параметры игры: тип рендерера, размер холста, контейнер для вставки и, что самое важное, настройки физики. В данном примере используется система 'arcade' с отключённым режимом отладки (debug: false). После создания экземпляра Phaser.Game с этой конфигурацией игра запускается.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'phaser-example',
physics: {
default: 'arcade',
arcade: { debug: false }
},
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Пример наглядно демонстрирует принцип управления вращением через ускорение и сопротивление в Arcade Physics. setAngularAcceleration изменяет скорость вращения, а setAngularDrag создаёт эффект торможения. Для экспериментов попробуйте изменить начальную угловую скорость, поиграть со значениями ускорения и сопротивления, или привязать эти параметры к состоянию другого игрового объекта (например, скорости персонажа). Также можно использовать deltaZ() для создания визуальных эффектов, зависящих от скорости вращения (следы, частицы).
