О чем этот пример
Физика — ключевой элемент для создания динамичных и правдоподобных игр. В Phaser плагин Matter.js предоставляет мощный и точный физический движок. Частая задача — позволить игроку управлять объектом, который взаимодействует с миром по законам физики: сталкивается, отскакивает и не может пройти сквозь стены. В этой статье мы разберем, как создать сцену с физикой Matter.js, добавить управляемый спрайт и настроить его движение с помощью клавиш-стрелок. Вы научитесь основам работы с телами Matter, управлению их скоростью и созданию границ игрового мира.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
cursors;
image;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('block', 'assets/sprites/block.png');
}
create ()
{
this.image = this.matter.add.image(400, 300, 'block');
this.matter.add.image(700, 200, 'block').setBounce(0.6);
this.matter.add.image(100, 500, 'block').setBounce(0.6);
this.matter.world.setBounds(0, 0, 800, 600);
this.cursors = this.input.keyboard.createCursorKeys();
}
update ()
{
if (this.cursors.left.isDown)
{
this.image.setVelocityX(-10);
}
else if (this.cursors.right.isDown)
{
this.image.setVelocityX(10);
}
else
{
this.image.setVelocityX(0);
}
if (this.cursors.up.isDown)
{
this.image.setVelocityY(-10);
}
else if (this.cursors.down.isDown)
{
this.image.setVelocityY(10);
}
else
{
this.image.setVelocityY(0);
}
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#1b1464',
parent: 'phaser-example',
physics: {
default: 'matter',
matter: {
gravity: {
x: 0,
y: 0
}
}
},
scene: Example
};
const game = new Phaser.Game(config);
Настройка сцены и физики Matter
Первым делом необходимо создать конфигурацию игры, указав Matter.js в качестве физического движка. Это ключевой шаг, без которого методы this.matter будут недоступны.
В конфигурации мы отключаем гравитацию по осям X и Y, чтобы наше тело двигалось только под воздействием клавиш и не падало вниз.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#1b1464',
parent: 'phaser-example',
physics: {
default: 'matter', // Активация плагина Matter.js
matter: {
gravity: {
x: 0, // Горизонтальная гравитация отключена
y: 0 // Вертикальная гравитация отключена
}
}
},
scene: Example
};
Создание физических тел и границ мира
В методе create() сцены происходит инициализация всех игровых объектов. Мы используем фабрику this.matter.add.image для создания спрайтов, которые сразу становятся физическими телами (rigid bodies).
Основное тело, которым будем управлять, сохраняется в свойство класса this.image. Два других блока добавлены как статичные препятствия с высоким коэффициентом упругости (setBounce(0.6)).
Метод this.matter.world.setBounds создает невидимые статические стены по краям игровой области, ограничивая движение всех физических тел.
create ()
{
// Создаем тело, которым будем управлять
this.image = this.matter.add.image(400, 300, 'block');
// Создаем два статических тела-препятствия с отскоком
this.matter.add.image(700, 200, 'block').setBounce(0.6);
this.matter.add.image(100, 500, 'block').setBounce(0.6);
// Устанавливаем границы физического мира (лево, верх, ширина, высота)
this.matter.world.setBounds(0, 0, 800, 600);
// Инициализируем слушатель клавиш-стрелок
this.cursors = this.input.keyboard.createCursorKeys();
}
Обработка ввода и управление скоростью
Логика движения реализована в методе update(), который вызывается на каждом кадре игры. Мы проверяем состояние клавиш-стрелок (isDown) и в зависимости от нажатой кнопки применяем к телу линейную скорость по оси X или Y с помощью метода setVelocityX() / setVelocityY().
Важный момент: если ни одна из клавиш направления не нажата, скорость сбрасывается до нуля. Это предотвращает бесконечное движение тела по инерции, так как в Matter.js, в отличие от Arcade Physics, тела по умолчанию не испытывают сопротивления.
update ()
{
// Управление движением по горизонтали
if (this.cursors.left.isDown)
{
this.image.setVelocityX(-10);
}
else if (this.cursors.right.isDown)
{
this.image.setVelocityX(10);
}
else
{
this.image.setVelocityX(0); // Остановка, если клавиши не нажаты
}
// Управление движением по вертикали
if (this.cursors.up.isDown)
{
this.image.setVelocityY(-10);
}
else if (this.cursors.down.isDown)
{
this.image.setVelocityY(10);
}
else
{
this.image.setVelocityY(0); // Остановка, если клавиши не нажаты
}
}
Ключевые методы Matter.js API
В примере используются несколько основных методов API Matter.js в Phaser:
* `this.matter.add.image(x, y, texture)` — фабричный метод для создания физического тела на основе изображения. Возвращает объект `MatterImage`.
* `.setVelocityX(value)` / `.setVelocityY(value)` — установка линейной скорости тела по соответствующей оси. Скорость задается в пикселях в секунду.
* `.setBounce(value)` — задает коэффициент реституции (упругости) тела. Значение 1 означает абсолютно упругий удар, 0 — абсолютно неупругий.
* `this.matter.world.setBounds(x, y, width, height)` — создает статические стены, ограничивающие мир. Все динамические тела будут с ними сталкиваться.
* `this.input.keyboard.createCursorKeys()` — возвращает объект `CursorKeys` для удобного отслеживания состояния стрелок вверх, вниз, влево и вправо.
Что попробовать дальше
Вы создали базовую систему управления физическим телом с помощью Matter.js. Основной принцип — прямое управление скоростью тела в ответ на ввод пользователя, что дает предсказуемую и отзывчивую механику.
**Идеи для экспериментов:**
1. Добавьте гравитацию в конфигурации (y: 0.2) и попробуйте управлять телом в прыжке, используя setVelocityY только при нажатии вверх.
2. Замените прямое присвоение скорости на применение силы с помощью applyForce(). Это создаст более инерционное и "тяжелое" управление.
3. Сделайте управляемого персонажа динамичным телом (как в примере), а платформы — статичными, используя isStatic: true при создании, чтобы создать классический платформер.
