О чем этот пример
Использование физического движка Matter.js в Phaser открывает возможности для создания реалистичных интерактивных симуляций. Этот пример демонстрирует, как быстро настроить мир с гравитацией, границами и стаком из 64 физических тел, которые отскакивают друг от друга и от стен. Такой подход полезен для прототипирования игровых механик, связанных с падением, столкновениями и хаотичным движением множества объектов, например, в головоломках или симуляторах.
Версия 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('ball', 'assets/sprites/pangball.png');
}
create ()
{
this.matter.world.setBounds(0, 0, 800, 600, 32, true, true, false, true);
// Add in a stack of balls
for (let i = 0; i < 64; i++)
{
const ball = this.matter.add.image(Phaser.Math.Between(100, 700), Phaser.Math.Between(-600, 0), 'ball');
ball.setCircle();
ball.setFriction(0.005);
ball.setBounce(1);
}
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#1d1d1d',
parent: 'phaser-example',
physics: {
default: 'matter',
matter: {
enableSleeping: true
}
},
scene: Example
};
const game = new Phaser.Game(config);
Настройка конфигурации Matter.js
Для использования Matter.js в проекте Phaser необходимо правильно настроить конфигурацию игры в объекте config. Ключевым моментом является указание physics.default и настройки в physics.matter.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#1d1d1d',
parent: 'phaser-example',
physics: {
default: 'matter', // Активация Matter.js как физического движка по умолчанию
matter: {
enableSleeping: true // Включение оптимизации: неактивные тела "засыпают"
}
},
scene: Example
};
Параметр enableSleeping: true позволяет движку переводить тела, которые остановились, в состояние "сна", что значительно снижает нагрузку на процессор в сценах со множеством статичных объектов.
Создание мира и его границ
В методе create() сцены происходит инициализация физического мира. Метод this.matter.world.setBounds() определяет его границы и их свойства.
create ()
{
this.matter.world.setBounds(0, 0, 800, 600, 32, true, true, false, true);
}
Метод принимает координаты левого верхнего угла (x, y), ширину и высоту области. Последние четыре булевых параметра определяют, будут ли у границ (слева, сверху, справа, снизу) активны столкновения. В данном случае у правой границы (false) столкновения отключены, что может создавать эффект "стока" для объектов. Число 32 — это толщина невидимой границы.
Генерация и настройка физических тел
Далее в цикле создаются 64 спрайта с физическим телом. Каждому телу задаются физические свойства, превращающие картинку в динамический объект.
for (let i = 0; i < 64; i++)
{
const ball = this.matter.add.image(Phaser.Math.Between(100, 700), Phaser.Math.Between(-600, 0), 'ball');
ball.setCircle();
ball.setFriction(0.005);
ball.setBounce(1);
}
1. this.matter.add.image(): Создает спрайт из изображения 'ball' и сразу прикрепляет к нему твердое тело Matter.js. Начальные координаты `xзадаются случайно в пределах сцены, аy` — выше верхней границы (от -600 до 0), чтобы мячи падали сверху.
2. ball.setCircle(): Заменяет прямоугольную форму коллайдера тела на круглую, соответствующую спрайту мяча. Это критически важно для корректного и реалистичного отскока.
3. ball.setFriction(0.005): Устанавливает очень низкий коэффициент трения, почти как у льда. Мячи будут долго скользить и вращаться после столкновений.
4. ball.setBounce(1): Задает коэффициент упругости (реституции), равный 1. Это означает идеально упругие столкновения без потери энергии — мячи отскакивают от стен и друг друга, не теряя скорости.
Почему мячи ведут себя так реалистично?
Поведение, которое мы видим, — это результат работы движка Matter.js, который по умолчанию включает гравитацию (она направлена вниз, по оси Y). Мячи падают под действием этой гравитации, сталкиваются с границами мира и друг с другом согласно заданным свойствам: форме (setCircle), упругости (setBounce) и трению (setFriction).
Поскольку мячи спавнятся в случайных точках выше экрана, они падают не одновременно, создавая каскадный эффект. Низкое трение и высокая упругость приводят к длительному, хаотичному движению, пока энергия не рассеется, и тела не "уснут" благодаря enableSleeping.
Что попробовать дальше
Этот пример — отличная стартовая точка для экспериментов с 2D-физикой в играх. Попробуйте изменить параметры: задать setBounce(0.3) для более "тяжелых" мячей, увеличить setFriction до 0.1, чтобы объекты быстрее останавливались, или отключить гравитацию через this.matter.world.setGravity(0, 0). Можно также изменить форму тел с помощью setRectangle() или добавить взаимодействие с игроком, сделав мячи кликабельными и добавляя им импульс applyForce по клику.
