О чем этот пример
В игровой механике часто нужны неподвижные объекты — стены, платформы, препятствия. Их обработка через обычные физические тела неэффективна, так как они никогда не двигаются. Phaser Arcade Physics предлагает специальный инструмент — статичную группу (Static Group). Эта статья покажет, как создать кольцо из статичных шаров и заставить спрайт отскакивать от них, что идеально подходит для создания игровых лабиринтов или арен.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
group;
sprite;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('mushroom', 'assets/sprites/mushroom2.png');
this.load.image('ball', 'assets/sprites/shinyball.png');
}
create ()
{
this.sprite = this.physics.add.image(400, 300, 'mushroom');
this.group = this.physics.add.staticGroup({
key: 'ball',
frameQuantity: 30
});
Phaser.Actions.PlaceOnRectangle(this.group.getChildren(), new Phaser.Geom.Rectangle(84, 84, 616, 416));
// We need to call this because placeOnRectangle has changed the coordinates of all the children
// If we don't call it, the static physics bodies won't be updated to reflect them
this.group.refresh();
this.sprite.setVelocity(100, 200).setBounce(1, 1).setCollideWorldBounds(true).setGravityY(200);
}
update ()
{
this.physics.world.collide(this.sprite, this.group);
}
}
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
parent: 'phaser-example',
physics: {
default: 'arcade',
arcade: {
debug: true
}
},
scene: Example
};
const game = new Phaser.Game(config);
Инициализация сцены и загрузка ассетов
В методе preload мы загружаем два изображения: гриб (mushroom) для движущегося спрайта и блестящий шар (ball) для статичных объектов. Обратите внимание на использование setBaseURL — это удобно для загрузки ресурсов из удаленного репозитория, но в реальном проекте вы, скорее всего, будете использовать локальные пути.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('mushroom', 'assets/sprites/mushroom2.png');
this.load.image('ball', 'assets/sprites/shinyball.png');
}
Создание физических тел
В методе create происходит основная настройка физики. Сначала создается динамическое тело — спрайт гриба с помощью this.physics.add.image. Оно будет двигаться под действием физики.
this.sprite = this.physics.add.image(400, 300, 'mushroom');
Затем создается статичная группа. Ключевой метод — this.physics.add.staticGroup. В параметрах мы указываем ключ текстуры (key) и количество создаваемых спрайтов (frameQuantity). Все созданные тела сразу будут статичными — они не подвержены силам гравитации или импульсам, но участвуют в коллизиях.
this.group = this.physics.add.staticGroup({
key: 'ball',
frameQuantity: 30
});
Расположение объектов и обновление физики
Созданные шары нужно расположить по фигуре. Для этого используется хелпер Phaser.Actions.PlaceOnRectangle. Он принимает массив детей группы (полученный через this.group.getChildren()) и объект прямоугольника Phaser.Geom.Rectangle. Дети будут равномерно распределены по периметру этой фигуры.
Phaser.Actions.PlaceOnRectangle(this.group.getChildren(), new Phaser.Geom.Rectangle(84, 84, 616, 416));
**Важный момент:** после изменения координат спрайтов через PlaceOnRectangle, их физические тела (статичные) не обновляются автоматически. Необходим вызов this.group.refresh(). Этот метод пересчитывает позиции и размеры всех физических тел в статичной группе, синхронизируя их с визуальными спрайтами.
this.group.refresh();
Настроим спрайт гриба: зададим начальную скорость, упругость (отскок), включим столкновение с границами мира и добавим гравитацию.
this.sprite.setVelocity(100, 200).setBounce(1, 1).setCollideWorldBounds(true).setGravityY(200);
Обработка столкновений и игровой цикл
В методе update, который вызывается каждый кадр, мы проверяем столкновение между движущимся спрайтом и всей статичной группой с помощью this.physics.world.collide. Phaser автоматически обрабатывает отскок, так как у спрайта установлено свойство setBounce(1, 1).
update ()
{
this.physics.world.collide(this.sprite, this.group);
}
Конфигурация игры
В конфигурации игры обязательно должен быть включен нужный физический плагин. В данном случае это arcade с опцией debug: true, которая отрисовывает хитбоксы — очень помогает при отладке.
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
parent: 'phaser-example',
physics: {
default: 'arcade',
arcade: {
debug: true
}
},
scene: Example
};
Что попробовать дальше
Использование статичной группы (staticGroup) — это оптимальный способ создания неподвижных препятствий в Phaser. Оно экономит ресурсы и упрощает код. Для экспериментов попробуйте
- Изменить форму расположения объектов с помощью
PlaceOnCircleилиPlaceOnEllipse - Динамически добавлять и удалять тела из группы, не забывая вызывать
refresh() - Использовать разные текстуры для элементов группы, передав массив в параметр
key
