О чем этот пример
Правильное управление вращением — основа динамичной игровой графики. В Phaser для этого есть два ключевых свойства: `angle` в градусах и `rotation` в радианах. Эта статья наглядно покажет, как они связаны и как использовать их для плавной анимации вращения ваших игровых объектов. Вы научитесь переключаться между градусами и радианами, что пригодится при работе с физикой, анимацией и математикой игрового мира.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
arrow;
text;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('arrow', 'assets/sprites/longarrow-white.png');
}
create ()
{
// The code isn't too important for this example
// What we're showing here is the angles, in degrees and radians,
// that a Phaser sprite uses when rotating.
//
// You can rotate a sprite by setting either property.
//
// `angle` is in degrees, from -180 to 180.
// `rotation` is in radians, from -PI to PI
//
// For example:
//
// sprite.angle = 45
//
// is the same as:
//
// sprite.rotation = 0.785
const labelStyle = { font: '16px courier', fill: '#00ff00', align: 'center' };
// Create a large circle, then draw the angles on it
const circle = new Phaser.Geom.Circle(400, 300, 225);
const labelCircle = new Phaser.Geom.Circle(400, 300, 265);
const graphics = this.add.graphics();
graphics.lineStyle(2, 0x00bb00, 1);
graphics.strokeCircleShape(circle);
graphics.beginPath();
for (let a = 0; a < 360; a += 22.5)
{
graphics.moveTo(400, 300);
const p = Phaser.Geom.Circle.CircumferencePoint(circle, Phaser.Math.DegToRad(a));
graphics.lineTo(p.x, p.y);
const lp = Phaser.Geom.Circle.CircumferencePoint(labelCircle, Phaser.Math.DegToRad(a));
let na = a;
if (a > 180)
{
na -= 360;
}
const rads = String(Phaser.Math.DegToRad(na)).substr(0, 5);
const info = `${na}°\n${rads}`;
const label = this.add.text(lp.x, lp.y, info, labelStyle).setOrigin(0.5);
}
graphics.strokePath();
this.arrow = this.add.sprite(400, 300, 'arrow').setOrigin(0, 0.5);
this.text = this.add.text(10, 10, '', { font: '16px Courier', fill: '#ffffff' });
}
update ()
{
this.arrow.angle += 0.2;
this.text.setText([
'Sprite Rotation',
`Angle: ${this.arrow.angle.toFixed(2)}`,
`Rotation: ${this.arrow.rotation.toFixed(2)}`
]);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Два свойства, одна цель
В Phaser каждый Sprite (и любой Game Object) имеет два свойства, управляющие его поворотом. Они взаимосвязаны, но используют разные единицы измерения, что может сбивать с толку новичков.
Свойство angle работает с привычными градусами. Его диапазон значений — от -180 до 180 градусов. Установка этого свойства автоматически пересчитывает внутреннее свойство rotation.
Свойство rotation работает с радианами. Это стандартная единица для математических вычислений в программировании, особенно в тригонометрии. Его диапазон — от -PI до PI (примерно от -3.14 до 3.14). Изменение rotation так же обновляет значение angle.
Эти два свойства — две стороны одной медали. Phaser позволяет использовать ту, которая удобнее в конкретной ситуации.
Визуализация углов на сцене
Пример кода создаёт наглядное пособие, рисуя круг с разметкой. Это помогает соотнести градусы с радианами и увидеть, как Phaser интерпретирует углы.
Сначала создаётся зелёный круг с помощью Phaser.Geom.Circle. Второй, больший круг (labelCircle) служит для позиционирования текстовых меток.
const circle = new Phaser.Geom.Circle(400, 300, 225);
const labelCircle = new Phaser.Geom.Circle(400, 300, 265);
Затем в цикле от 0 до 360 градусов с шагом 22.5 рисуются лучи от центра к окружности и добавляются подписи. Ключевой метод Phaser.Geom.Circle.CircumferencePoint получает точку на окружности для заданного угла.
const p = Phaser.Geom.Circle.CircumferencePoint(circle, Phaser.Math.DegToRad(a));
Обратите внимание на преобразование градусов в радианы с помощью Phaser.Math.DegToRad. Это необходимо, потому что большинство геометрических методов Phaser, включая CircumferencePoint, ожидают углы в радианах. Для отображения текст метки формируется из градусов и их радианного эквивалента.
Спрайт в действии
В центре визуализации размещается спрайт стрелки. Важный момент — установка точки привязки (origin). По умолчанию она в центре спрайта (0.5, 0.5), но для вращения, как у часовой стрелки, её сдвигают к началу изображения.
this.arrow = this.add.sprite(400, 300, 'arrow').setOrigin(0, 0.5);
Метод setOrigin(0, 0.5) устанавливает точку вращения на левом краю по горизонтали и по центру спрайта по вертикали. Теперь стрелка будет вращаться вокруг своего левого конца, как стрелка на циферблате.
В методе update происходит главное действие — непрерывное вращение. Увеличивая свойство angle на небольшую величину каждый кадр, мы создаём плавную анимацию.
this.arrow.angle += 0.2;
Одновременно в текстовом поле обновляются текущие значения обоих свойств, демонстрируя их синхронность. Увеличение angle на 0.2 градуса за кадр автоматически приводит к изменению rotation.
Какой метод использовать?
Выбор между angle и rotation зависит от контекста.
Используйте angle, когда:
* Работаете с дизайнерами или редакторами уровней, где углы задаются в градусах.
* Вращение интуитивно понятнее описывать градусами (например, поворот на 90°).
* Задаёте статичное положение объекта.
Используйте rotation, когда:
* Производите математические вычисления, особенно с тригонометрическими функциями (Math.sin, Math.cos).
* Работаете с физическим движком Phaser (Arcade Physics, Matter.js), который оперирует радианами.
* Нужна максимальная производительность в критичных по времени операциях (прямое присваивание радиан может быть чуть быстрее).
Помните, что установка одного свойства мгновенно обновляет другое, поэтому можно свободно смешивать их использование в коде, выбирая наиболее удобный вариант для каждой конкретной задачи.
Что попробовать дальше
Свойства angle и rotation — это мощный и гибкий дуэт для управления вращением в Phaser. Понимание их взаимосвязи и контекста использования избавит от путаницы и откроет путь к созданию сложного и красивого игрового поведения. Для экспериментов попробуйте: заменить this.arrow.angle += 0.2 на прямое изменение rotation; заставить спрайт вращаться к позиции курсора мыши, используя Math.atan2 (который возвращает угол в радианах); или привязать вращение к физической силе, используя body.angularVelocity.
