О чем этот пример
При создании игры часто нужны неподвижные объекты: платформы, стены, препятствия. Phaser Arcade Physics позволяет легко создавать статические тела, которые не двигаются под действием физики, но с которыми могут сталкиваться динамические объекты. Этот подход экономит ресурсы и упрощает логику игры. В статье разберем пример, где один спрайт отскакивает от трех статических изображений, и объясним ключевые методы.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
static3;
static2;
static1;
sprite;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bar', 'assets/sprites/healthbar.png');
this.load.image('mushroom', 'assets/sprites/mushroom2.png');
}
create ()
{
this.sprite = this.physics.add.image(100, 100, 'mushroom');
this.static1 = this.physics.add.staticImage(400, 100, 'bar');
this.static2 = this.physics.add.staticImage(100, 400, 'bar');
this.static3 = this.physics.add.staticImage(500, 300, 'bar');
this.sprite.body.setVelocity(100, 200).setBounce(1, 1).setCollideWorldBounds(true);
}
update ()
{
this.physics.world.collide(this.sprite, [ this.static1, this.static2, this.static3 ]);
}
}
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
parent: 'phaser-example',
physics: {
default: 'arcade',
arcade: {
gravity: { y: 200 },
debug: true
}
},
scene: Example
};
const game = new Phaser.Game(config);
Настройка сцены и загрузка ресурсов
Класс Example расширяет Phaser.Scene. В нем объявлены свойства для хранения ссылок на спрайты: static1, static2, static3 для статических тел и sprite для динамического.
В методе preload() задается базовый URL для загрузки и загружаются два изображения: спрайт гриба (mushroom) и изображение для статической полосы (bar).
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bar', 'assets/sprites/healthbar.png');
this.load.image('mushroom', 'assets/sprites/mushroom2.png');
}
Создание физических тел в create()
Метод create() инициализирует все игровые объекты. Динамическое тело создается с помощью this.physics.add.image. Это спрайт, на который воздействует гравитация и который может двигаться.
this.sprite = this.physics.add.image(100, 100, 'mushroom');
Статические тела создаются методом this.physics.add.staticImage. Они сразу добавляются в физический мир как неподвижные объекты.
this.static1 = this.physics.add.staticImage(400, 100, 'bar');
this.static2 = this.physics.add.staticImage(100, 400, 'bar');
this.static3 = this.physics.add.staticImage(500, 300, 'bar');
Затем для динамического спрайта настраиваются физические свойства: задается начальная скорость, упругость (отскок) и включение столкновений с границами мира.
this.sprite.body.setVelocity(100, 200).setBounce(1, 1).setCollideWorldBounds(true);
Обработка столкновений в update()
Метод update() вызывается каждый кадр игры. В нем проверяются столкновения между динамическим спрайтом и массивом статических тел с помощью this.physics.world.collide. Phaser автоматически обрабатывает физику столкновения и отскока для этих объектов.
update ()
{
this.physics.world.collide(this.sprite, [ this.static1, this.static2, this.static3 ]);
}
Конфигурация игры и физики
Объект config содержит основные настройки игры. Ключевой раздел — physics. Здесь активируется система Arcade Physics, задается гравитация и включается отладочный режим, который рисует контуры физических тел.
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
parent: 'phaser-example',
physics: {
default: 'arcade',
arcade: {
gravity: { y: 200 },
debug: true
}
},
scene: Example
};
Игра инициируется созданием нового экземпляра Phaser.Game с этой конфигурацией.
const game = new Phaser.Game(config);
Отличие staticImage от обычного image
Главное отличие между this.physics.add.image и this.physics.add.staticImage — в типе создаваемого физического тела.
- **Динамическое тело** (image) реагирует на силы: гравитацию, скорость, импульсы. Его можно двигать методами физики.
- **Статическое тело** (staticImage) имеет массу, но его позиция фиксирована физическим движком. Оно не падает под действием гравитации и не сдвигается при столкновении, что делает его идеальным для платформ и стен.
Использование статических тел для неподвижных объектов — это оптимизация. Движок тратит меньше ресурсов на расчет их движения.
Практические советы
1. **Отладка:** Включите debug: true в конфиге Arcade Physics, чтобы видеть контуры тел. Синие контуры — динамические, зеленые — статические.
2. **Группы статических тел:** Если статических объектов много, создайте физическую группу (this.physics.add.staticGroup) для более эффективного управления и проверки столкновений.
3. **Изменение статического тела:** Если вам все же нужно сдвинуть статический объект после создания, вызовите для него метод body.updateFromGameObject(). Не забывайте, что это требует пересчета в движке.
4. **Производительность:** Столкновения между динамическим телом и массивом статических (collide(sprite, array)) работают эффективно. Для сложных сцен используйте методы коллизии с группами.
Что попробовать дальше
Использование статических тел — простой и производительный способ создания неподвижных препятствий и платформ в играх на Phaser. Они идеально подходят для уровня, декораций и любых объектов, которые не должны двигаться под действием физики.
**Идеи для экспериментов:**
1. Замените массив статических тел на staticGroup и проверьте столкновения с группой.
2. Попробуйте изменить гравитацию на { x: 100, y: 0 }, чтобы создать эффект "бокового" притяжения.
3. Добавьте несколько динамических спрайтов и заставьте их сталкиваться друг с другом и со статическими объектами.
