О чем этот пример
Физический движок Arcade в Phaser предоставляет удобные инструменты для управления движением объектов. В этой статье мы разберем, как реализовать стрельбу снарядами в направлении вращающейся пушки, используя метод `velocityFromAngle`. Этот подход полезен для создания классических аркадных игр, танковых дуэлей или космических шутеров, где направление выстрела зависит от угла поворота оружия.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('cannon_head', 'assets/tests/timer/cannon_head.png');
this.load.spritesheet('ball', 'assets/sprites/balls.png', { frameWidth: 17, frameHeight: 17 });
}
create ()
{
const balls = this.physics.add.group({
active: false,
bounceX: 1,
bounceY: 1,
collideWorldBounds: true,
frame: [ 0, 1, 2, 3, 4 ],
key: 'ball',
quantity: 12,
setXY: { x: 400, y: 300 }
});
const cannon = this.physics.add.image(400, 300, 'cannon_head')
.setAngularVelocity(60);
this.time.addEvent({
delay: 100,
startAt: 100,
repeat: balls.getLength() - 1,
callback: () =>
{
const ball = balls.getFirstDead();
ball.setActive(true);
this.physics.velocityFromAngle(cannon.angle, 300, ball.body.velocity);
}
});
}
}
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);
Подготовка ресурсов и создание группы снарядов
В методе preload загружаются два изображения: спрайт пушки и спрайтшит для шариков-снарядов. Обратите внимание на параметры загрузки спрайтшита: указывается ширина и высота одного кадра.
this.load.image('cannon_head', 'assets/tests/timer/cannon_head.png');
this.load.spritesheet('ball', 'assets/sprites/balls.png', { frameWidth: 17, frameHeight: 17 });
В create создается физическая группа balls. Ключевые настройки:
* active: false — все объекты в группе изначально неактивны.
* bounceX/Y: 1 — снаряды будут идеально отскакивать от границ.
* collideWorldBounds: true — включает столкновение с границами мира.
* frame — массив индексов кадров из спрайтшита.
* quantity: 12 — группа сразу создаст 12 физических тел.
* setXY — все тела будут расположены в одной точке (400, 300).
const balls = this.physics.add.group({
active: false,
bounceX: 1,
bounceY: 1,
collideWorldBounds: true,
frame: [ 0, 1, 2, 3, 4 ],
key: 'ball',
quantity: 12,
setXY: { x: 400, y: 300 }
});
Создание и вращение пушки
Пушка создается как физический спрайт с помощью this.physics.add.image. После создания ей сразу же задается постоянная угловая скорость с помощью метода .setAngularVelocity(60). Это заставляет пушку непрерывно вращаться вокруг своей центральной точки.
const cannon = this.physics.add.image(400, 300, 'cannon_head')
.setAngularVelocity(60);
Запуск таймера и логика выстрела
Для последовательного выпуска снарядов используется this.time.addEvent. Событие настраивается так, чтобы срабатывать каждые 100 мс (delay), начиная через 100 мс после создания (startAt), и повторяться на один раз меньше, чем количество снарядов в группе. Это гарантирует, что каждый из 12 снарядов будет выпущен ровно один раз с небольшой задержкой.
Внутри коллбэка происходит основная магия:
1. balls.getFirstDead() — получаем первый неактивный ("мёртвый") снаряд из группы.
2. ball.setActive(true) — активируем его, делая видимым и подверженным физике.
3. this.physics.velocityFromAngle(cannon.angle, 300, ball.body.velocity) — ключевой вызов. Он вычисляет вектор скорости на основе текущего угла пушки (cannon.angle), заданной мощности (300 пикселей в секунду) и записывает результат в свойство velocity физического тела снаряда (ball.body).
this.time.addEvent({
delay: 100,
startAt: 100,
repeat: balls.getLength() - 1,
callback: () =>
{
const ball = balls.getFirstDead();
ball.setActive(true);
this.physics.velocityFromAngle(cannon.angle, 300, ball.body.velocity);
}
});
Настройка игры и физики
Конфигурация игры стандартна, но важно обратить внимание на настройки физического движка Arcade. В данном примере отладка (debug) отключена. При значении true вы увидите хитбоксы (границы тел) всех физических объектов, что полезно для разработки.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'phaser-example',
physics: {
default: 'arcade',
arcade: {
debug: false
}
},
scene: Example
};
Что попробовать дальше
Метод velocityFromAngle — это элегантный способ преобразовать угол поворота в вектор скорости, идеально подходящий для механик стрельбы. Для экспериментов попробуйте изменить угловую скорость пушки, силу выстрела или интервал между выстрелами. Можно добавить управление пушкой с клавиатуры, реализовать перезарядку или создать разные типы снарядов с уникальными свойствами отскока и скоростью.
