О чем этот пример
В Arcade Physics Phaser есть простое, но мощное свойство `angularVelocity`, которое управляет скоростью вращения тела. Этот пример показывает, как создать реалистичное управление самолётом, где поворот влияет на направление движения. Вы научитесь связывать вращение спрайта с его вектором скорости, создавая классическую механику полёта, и использовать полезный метод `wrap` для бесшовного перемещения объекта по краям игрового мира.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
plane;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('clouds', 'assets/skies/clouds.png');
this.load.image('plane', 'assets/sprites/ww2plane90.png');
}
create ()
{
this.add.image(0, 0, 'clouds').setOrigin(0, 0);
this.plane = this.physics.add.image(400, 300, 'plane')
.setCircle(24, 0, 7.5)
.setVelocity(0, -100);
this.input.keyboard
.on('keydown-LEFT', () => { this.plane.setAngularVelocity(-60); })
.on('keydown-RIGHT', () => { this.plane.setAngularVelocity(60); })
.on('keydown-UP', () => { this.plane.setAngularVelocity(0); });
}
update ()
{
this.physics.velocityFromAngle(this.plane.angle, 150, this.plane.body.velocity);
this.physics.world.wrap(this.plane, 32);
}
}
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);
Подготовка сцены и загрузка ассетов
Класс Example расширяет Phaser.Scene. В методе preload задаётся базовый URL для загрузки и загружаются два изображения: фон с облаками и спрайт самолёта.
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('clouds', 'assets/skies/clouds.png');
this.load.image('plane', 'assets/sprites/ww2plane90.png');
Создание физического тела и настройка управления
В методе create сначала добавляется фоновое изображение. Затем создаётся физическое тело самолёта с помощью this.physics.add.image. Ключевые моменты:
- Метод .setCircle(24, 0, 7.5) задаёт круглую коллизию для спрайта самолёта (радиус 24 пикселя со смещением). Это важно для корректного взаимодействия с физикой.
- .setVelocity(0, -100) задаёт начальную скорость движения вверх.
Управление привязывается к клавиатуре: клавиши LEFT/RIGHT изменяют угловую скорость (angularVelocity), заставляя самолёт вращаться, а клавиша UP сбрасывает её до нуля.
this.plane = this.physics.add.image(400, 300, 'plane')
.setCircle(24, 0, 7.5)
.setVelocity(0, -100);
this.input.keyboard
.on('keydown-LEFT', () => { this.plane.setAngularVelocity(-60); })
.on('keydown-RIGHT', () => { this.plane.setAngularVelocity(60); })
.on('keydown-UP', () => { this.plane.setAngularVelocity(0); });
Связь угла поворота и вектора скорости
Сердце механики полёта находится в методе `update`. Чтобы самолёт летел в ту сторону, куда смотрит его нос, используется метод `this.physics.velocityFromAngle`.
- Первый аргумент — текущий угол поворота спрайта (`this.plane.angle`).
- Второй аргумент — величина скорости (150).
- Третий аргумент — целевой объект вектора скорости (`this.plane.body.velocity`).
Этот метод каждый кадр пересчитывает вектор скорости (velocity.x и velocity.y) на основе угла, создавая ощущение реалистичного полёта.
this.physics.velocityFromAngle(this.plane.angle, 150, this.plane.body.velocity);
Бесшовный переход через границы мира
Чтобы самолёт не улетал за границы экрана, используется метод `this.physics.world.wrap`.
- Первый аргумент — объект для обёртки (`this.plane`).
- Второй аргумент — отступ (padding) в пикселях (32). Это означает, что объект начнёт переходить на противоположную сторону, когда его центр отдалится от края мира на 32 пикселя.
Этот подход удобнее, чем ручная проверка координат, и создаёт плавный, непрерывный игровой мир.
this.physics.world.wrap(this.plane, 32);
Конфигурация игры и запуск
В конце файла определяется объект конфигурации игры config и создаётся её экземпляр. Важно настроить физическую систему arcade.
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);
Что попробовать дальше
Пример демонстрирует элегантную связку angularVelocity и velocityFromAngle для создания интуитивного управления летательным аппаратом. Для экспериментов попробуйте изменить скорость вращения или величину скорости полёта, добавьте ускорение/торможение по клавише DOWN или реализуйте стрельбу в направлении движения самолёта, используя его текущий угол.
