О чем этот пример
В игровой разработке часто возникает необходимость остановить игровой мир — например, для показа меню паузы или замедления времени. Механизм паузы встроен в физический движок Matter.js в Phaser, но его использование имеет нюансы. В этой статье мы разберем рабочий пример управления паузой физики, объясним, как корректно ставить мир на паузу и возобновлять его, а также почему важно использовать `addCapture` для предотвращения побочных действий клавиши.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
preload ()
{
// this.load.setBaseURL('https://cdn.phaserfiles.com/v385');
this.load.image('ball', 'https://labs.phaser.io/assets/sprites/pangball.png');
}
create ()
{
this.matter.world.setBounds(0, 0, 800, 600, 32, true, true, false, true);
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);
}
let p = false;
this.input.keyboard.on("keydown-SPACE", (event) => {
p = !p;
if (! p) {
this.matter.resume();
} else {
this.matter.pause();
}
});
this.input.keyboard.addCapture("SPACE");
}
}
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);
Подготовка сцены и настройка физики
Вся логика примера находится в классе сцены. В методе preload загружается одно изображение мяча, которое будет использоваться для множества физических тел.
Ключевым моментом является конфигурация физики в объекте config. Мы указываем, что используем движок Matter.js (default: 'matter') и включаем в нем опцию enableSleeping. Это позволяет телам "засыпать" при отсутствии движения, что оптимизирует производительность.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#1d1d1d',
parent: 'phaser-example',
physics: {
default: 'matter',
matter: {
enableSleeping: true
}
},
scene: Example
};
Создание физического мира и тел
В методе create мы настраиваем мир и наполняем его объектами. Сначала задаются границы мира с помощью this.matter.world.setBounds(). Последние булевые параметры метода определяют, с каких сторон ставить стены; в нашем случае стены есть слева, справа и снизу.
Затем в цикле создается 64 мяча. Каждый мяч — это MatterImage, созданное через this.matter.add.image. Его начальная позиция по X случайна в пределах сцены, а по Y — может быть даже выше видимой области (от -600 до 0), чтобы мячи падали сверху.
Сразу после создания каждому телу задаются физические свойства:
- setCircle() — определяет форму тела как круг (по умолчанию тело-прямоугольник).
- setFriction(0.005) — устанавливает очень низкое трение.
- setBounce(1) — задает идеально упругий отскок (коэффициент восстановления 1).
this.matter.world.setBounds(0, 0, 800, 600, 32, true, true, false, true);
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);
}
Логика переключения паузы по клавише SPACE
Здесь реализуется основная механика управления паузой. Объявляется флаг `p`, который отслеживает текущее состояние (пауза активна или нет).
На событие keydown-SPACE вешается обработчик, который инвертирует значение флага `p. В зависимости от нового состояния флага вызывается либоthis.matter.resume(), либоthis.matter.pause()`. Эти методы глобально останавливают и возобновляют вычисления физики для всего мира Matter.js.
let p = false;
this.input.keyboard.on("keydown-SPACE", (event) => {
p = !p;
if (!p) {
this.matter.resume();
} else {
this.matter.pause();
}
});
Зачем нужен addCapture и важные детали
Строка this.input.keyboard.addCapture("SPACE") — критически важная деталь для корректной работы в браузере. По умолчанию клавиша SPACE (пробел) имеет системное действие — прокрутка страницы. Если игровое окно встроено в веб-страницу, нажатие пробела будет одновременно ставить игру на паузу и прокручивать страницу вниз, что создает неприятный пользовательский опыт.
Метод addCapture() перехватывает событие от указанной клавиши, предотвращая его всплытие и выполнение действий браузера по умолчанию. Это стандартная практика для игровых управляющих клавиш.
Важно понимать, что this.matter.pause() и this.matter.resume() управляют только физическим движком. Анимации, таймеры и обновление логики сцены (в update) продолжают работать. Для полной паузы игры потребуется дополнительная логика.
this.input.keyboard.addCapture("SPACE");
Что попробовать дальше
Управление паузой физики в Phaser с Matter.js сводится к вызову двух методов: pause() и resume(). Пример демонстрирует надежный паттерн с флагом состояния и перехватом клавиши. Для экспериментов попробуйте
- Добавить визуальный индикатор состояния паузы (текст, затемнение)
- Связать паузу физики с остановкой анимаций спрайтов
- Реализовать систему "буллет-тайма" (замедления), модифицируя
timeScaleмира Matter черезthis.matter.world.setTimeScale(0.5) - Управлять паузой для отдельных групп тел, а не для всего мира сразу
