О чем этот пример
Разработка игр с физикой — это не только логика взаимодействий, но и постоянная борьба с невидимыми силами. Отладка столкновений, проверка свойств тел и контроль за соединениями могут превратиться в долгий процесс угадывания. Встроенный debug-режим Matter.js в Phaser 3 позволяет визуализировать физический мир, экономя часы разработки. Эта статья покажет, как настроить и использовать debug-отрисовку для анализа статических и динамических тел, ограничений (joints), скоростей и коллизий. Вы научитесь быстро диагностировать проблемы и точечно включать только нужные визуальные подсказки.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
constructor ()
{
super();
}
create ()
{
this.matter.world.setBounds();
// First, we'll create a few static bodies
const body1 = this.matter.add.rectangle(250, 50, 200, 32, { isStatic: true });
this.matter.add.polygon(600, 100, 3, 40, { isStatic: true });
this.matter.add.polygon(100, 500, 8, 50, { isStatic: true });
this.matter.add.rectangle(750, 200, 16, 180, { isStatic: true });
// Now a body that shows off internal edges + convex hulls
const star = '50 0 63 38 100 38 69 59 82 100 50 75 18 100 31 59 0 38 37 38';
this.matter.add.fromVertices(700, 500, star, { restitution: 0.5 }, true);
// Some different joint types
const body2 = this.matter.add.circle(150, 250, 16);
const body3 = this.matter.add.circle(400, 450, 16);
const body4 = this.matter.add.circle(500, 50, 16);
// A spring, because length > 0 and stiffness < 0.9
this.matter.add.spring(body1, body2, 140, 0.001);
// A joint, because length > 0 and stiffness > 0.1
this.matter.add.worldConstraint(body3, 140, 1, { pointA: { x: 400, y: 250 }});
// A pin, because length = 0 and stiffness > 0.1
this.matter.add.worldConstraint(body4, 0, 1, { pointA: { x: 500, y: 50 }});
// Finally some random dynamic bodies
for (let i = 0; i < 12; i++)
{
let x = Phaser.Math.Between(100, 700);
let y = Phaser.Math.Between(100, 500);
if (Math.random() < 0.5)
{
let sides = Phaser.Math.Between(3, 14);
let radius = Phaser.Math.Between(8, 50);
this.matter.add.polygon(x, y, sides, radius, { restitution: 0.5 });
}
else
{
let width = Phaser.Math.Between(16, 128);
let height = Phaser.Math.Between(8, 64);
this.matter.add.rectangle(x, y, width, height, { restitution: 0.5 });
}
}
this.matter.add.mouseSpring();
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#000000',
parent: 'phaser-example',
physics: {
default: 'matter',
matter: {
enableSleeping: true,
debug: {
showAxes: false,
showAngleIndicator: true,
angleColor: 0xe81153,
showBroadphase: false,
broadphaseColor: 0xffb400,
showBounds: false,
boundsColor: 0xffffff,
showVelocity: true,
velocityColor: 0x00aeef,
showCollisions: true,
collisionColor: 0xf5950c,
showSeparations: false,
separationColor: 0xffa500,
showBody: true,
showStaticBody: true,
showInternalEdges: true,
renderFill: false,
renderLine: true,
fillColor: 0x106909,
fillOpacity: 1,
lineColor: 0x28de19,
lineOpacity: 1,
lineThickness: 1,
staticFillColor: 0x0d177b,
staticLineColor: 0x1327e4,
showSleeping: true,
staticBodySleepOpacity: 1,
sleepFillColor: 0x464646,
sleepLineColor: 0x999a99,
showSensors: true,
sensorFillColor: 0x0d177b,
sensorLineColor: 0x1327e4,
showPositions: true,
positionSize: 4,
positionColor: 0xe042da,
showJoint: true,
jointColor: 0xe0e042,
jointLineOpacity: 1,
jointLineThickness: 2,
pinSize: 4,
pinColor: 0x42e0e0,
springColor: 0xe042e0,
anchorColor: 0xefefef,
anchorSize: 4,
showConvexHulls: true,
hullColor: 0xd703d0
}
}
},
scene: Example
};
let game = new Phaser.Game(config);
Включение и базовая настройка debug-режима
Для активации визуальной отладки необходимо в конфигурации игры, внутри раздела physics.matter, установить объект debug. Именно в нем перечисляются все возможные опции отрисовки. Включение режима происходит автоматически, если этот объект присутствует.
physics: {
default: 'matter',
matter: {
enableSleeping: true,
debug: {
// Все опции отрисовки указываются здесь
showBody: true,
renderLine: true
}
}
}
Ключевой параметр showBody включает отрисовку всех физических тел. renderLine определяет, что тела будут обведены контуром, а не залиты цветом. Это базовые настройки, которые делают физические формы видимыми на экране.
Визуализация свойств физических тел
Debug-режим позволяет отображать не только форму тела, но и его внутреннее состояние. Это критически важно для понимания поведения объектов в реальном времени.
debug: {
showAngleIndicator: true,
angleColor: 0xe81153,
showVelocity: true,
velocityColor: 0x00aeef,
showPositions: true,
positionSize: 4,
positionColor: 0xe042da
}
* showAngleIndicator: Рисует дугу, показывающую угол поворота тела. Цвет задается angleColor.
* showVelocity: Отображает вектор текущей скорости каждого тела. Длина линии соответствует скорости, направление — вектору движения.
* showPositions: Помечает центр масс (anchor) каждого тела точкой. Ее размер и цвет настраиваются positionSize и positionColor.
Эти опции превращают абстрактные физические свойства в понятные графические метки.
Отладка коллизий и внутренней структуры
Сложные составные тела и многоугольники требуют особого внимания. Matter.js предоставляет инструменты для отладки их геометрии.
debug: {
showCollisions: true,
collisionColor: 0xf5950c,
showInternalEdges: true,
showConvexHulls: true,
hullColor: 0xd703d0
}
* showCollisions: Подсвечивает области активных столкновений между телами. Это самый прямой способ увидеть, где происходит соприкосновение.
* showInternalEdges: Показывает внутренние ребра у составных тел (созданных через fromVertices). Без этой опции такое тело может отображаться как выпуклая оболочка.
* showConvexHulls: Отрисовывает выпуклую оболочку для составных тел. Полезно для понимания, как физический движок "видит" сложную форму.
На примере звезды (fromVertices) включение showInternalEdges и showConvexHulls наглядно демонстрирует разницу между ее визуальной формой и физическим представлением.
Статические тела, сенсоры и режим сна
Поведение статических тел и сенсоров часто нужно проверить отдельно. Также полезно видеть, какие тела "уснули" для оптимизации.
debug: {
showStaticBody: true,
staticLineColor: 0x1327e4,
showSensors: true,
sensorLineColor: 0x1327e4,
showSleeping: true,
sleepLineColor: 0x999a99
}
* showStaticBody и staticLineColor: Контролируют отображение статических тел (с isStatic: true). Их можно окрасить в отличный от динамических цвет.
* showSensors: Визуализирует сенсоры (тела с isSensor: true), которые обнаруживают пересечения, но не имеют физического ответа.
* showSleeping: Показывает тела, перешедшие в режим сна (когда они неподвижны). Цвет таких тел меняется на sleepLineColor и sleepFillColor. Это помогает понять, какие объекты больше не участвуют в расчетах.
Визуализация соединений: пружины, шарниры, пины
Соединения (joints/constraints) — мощный инструмент Matter.js. Их отладка без визуализации почти невозможна.
debug: {
showJoint: true,
jointColor: 0xe0e042,
springColor: 0xe042e0,
pinSize: 4,
pinColor: 0x42e0e0
}
В примере создаются три типа связей между телами:
1. **Пружина (Spring)**: Создается методом `this.matter.add.spring`. В debug-режиме отображается линией цвета `springColor`.
2. **Шарнир/Ограничение (Joint)**: Создается `this.matter.add.worldConstraint` с длиной > 0 и высокой жесткостью (`stiffness: 1`). Рисуется цветом `jointColor`.
3. **Пин (Pin)**: Тот же `worldConstraint`, но с нулевой длиной (`length: 0`). В точке крепления отображается маркер, заданный `pinSize` и `pinColor`.
Опция showJoint отвечает за отрисовку всех типов соединений.
Что попробовать дальше
Debug-режим Matter.js — это ваш рентгеновский аппарат для физического мира игры. Настраивая его, вы переходите от предположений к точным данным о коллизиях, скоростях и связях. Начните с включения showBody, showVelocity и showCollisions для общей картины, затем добавляйте специфичные опции вроде showInternalEdges или showSleeping по мере необходимости.
Для экспериментов попробуйте:
1. Создать сложный уровень со статической геометрией и включить только showStaticBody и showConvexHulls.
2. Построить цепь или маятник с помощью worldConstraint и наблюдать за шарнирами с showJoint: true.
3. Поиграть с цветами (lineColor, fillColor) для создания собственной, интуитивно понятной цветовой схемы отладки под стиль вашей игры.
