О чем этот пример
В геймдеве часто нужно выходить за рамки простых прямоугольников и кругов. Этот пример демонстрирует мощный подход Phaser 3 и Matter.js: создание полигональных спрайтов с последующим наделением их точной физической формой на основе пользовательских вершин. Вы научитесь создавать сталкивающиеся объекты произвольной формы, такие как стрелы, шевроны или звёзды, с полным контролем над их физическими свойствами – от упругости до трения воздуха.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
this.matter.world.setBounds().disableGravity();
const arrow = '40 0 40 20 100 20 100 80 40 80 40 100 0 50';
const chevron = '100 0 75 50 100 100 25 100 0 50 25 0';
const star = '50 0 63 38 100 38 69 59 82 100 50 75 18 100 31 59 0 38 37 38';
const poly1 = this.add.polygon(400, 300, arrow, 0x0000ff, 0.2);
this.matter.add.gameObject(poly1, { shape: { type: 'fromVerts', verts: arrow, flagInternal: true } });
poly1.setVelocity(6, 3);
poly1.setAngularVelocity(0.01);
poly1.setBounce(1);
poly1.setFriction(0, 0, 0);
const poly2 = this.add.polygon(400, 100, chevron, 0xff0000, 0.2);
this.matter.add.gameObject(poly2, { shape: { type: 'fromVerts', verts: chevron, flagInternal: true } });
poly2.setVelocity(6, 3);
poly2.setAngularVelocity(0.01);
poly2.setBounce(1);
poly2.setFriction(0, 0, 0);
const poly3 = this.add.polygon(600, 400, star, 0x00ff00, 0.2);
this.matter.add.gameObject(poly3, { shape: { type: 'fromVerts', verts: star, flagInternal: true } });
poly3.setVelocity(4, -2);
poly3.setBounce(1);
poly3.setFriction(0, 0, 0);
poly3.setFrictionAir(0.005);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#efefef',
parent: 'phaser-example',
physics: {
default: 'matter',
matter: {
debug: {
renderFill: false,
showInternalEdges: true,
showConvexHulls: true
}
}
},
scene: Example
};
const game = new Phaser.Game(config);
Настройка физического мира
Первым делом в методе create() настраивается физический мир Matter.js. Границы мира устанавливаются с помощью setBounds(), а гравитация отключается через disableGravity(). Это создаёт идеальную среду для демонстрации движения тел без внешних сил.
this.matter.world.setBounds().disableGravity();
Определение форм через строки вершин
Формы полигонов задаются строками координат. Каждая пара чисел — это координаты X и Y вершины относительно центра фигуры. Например, строка для стрелки описывает её контур от острия к хвосту. Этот подход позволяет легко хранить и передавать сложные формы.
const arrow = '40 0 40 20 100 20 100 80 40 80 40 100 0 50';
const chevron = '100 0 75 50 100 100 25 100 0 50 25 0';
const star = '50 0 63 38 100 38 69 59 82 100 50 75 18 100 31 59 0 38 37 38';
Создание графического и физического объекта
Процесс состоит из двух шагов. Сначала создаётся визуальный полигон с помощью this.add.polygon(). Затем, используя this.matter.add.gameObject(), к этому графическому объекту привязывается физическое тело. Ключевой параметр shape определяет, что форма тела (Body) должна быть построена из вершин (fromVerts). Параметр flagInternal: true помогает Matter.js корректно обрабатывать внутренние рёбра сложных вогнутых полигонов.
const poly1 = this.add.polygon(400, 300, arrow, 0x0000ff, 0.2);
this.matter.add.gameObject(poly1, { shape: { type: 'fromVerts', verts: arrow, flagInternal: true } });
Настройка физических свойств
После создания физического тела ему задаются динамические свойства через методы, предоставляемые плагином Matter. setVelocity() задаёт начальную скорость, setAngularVelocity() — скорость вращения. setBounce(1) делает тело абсолютно упругим. setFriction(0, 0, 0) убирает трение о другие тела и поверхность, а setFrictionAir() регулирует сопротивление воздуха, замедляющее объект.
poly1.setVelocity(6, 3);
poly1.setAngularVelocity(0.01);
poly1.setBounce(1);
poly1.setFriction(0, 0, 0);
// И для третьего тела можно добавить сопротивление воздуха
poly3.setFrictionAir(0.005);
Конфигурация отладки (debug)
Файл конфигурации содержит важные настройки для визуализации физических тел в режиме отладки. renderFill: false отключает заливку, показывая только контур. showInternalEdges: true подсвечивает внутренние рёбра вогнутых полигонов, а showConvexHulls: true показывает выпуклые оболочки, на которые Matter.js разбивает сложные формы для расчётов. Это невероятно полезно для понимания, как движок "видит" ваши объекты.
physics: {
default: 'matter',
matter: {
debug: {
renderFill: false,
showInternalEdges: true,
showConvexHulls: true
}
}
}
Что попробовать дальше
Использование вершин для создания физических тел открывает путь к сложной и разнообразной игровой механике: от неправильной формы астероидов до детализированных персонажей. Для экспериментов попробуйте
- Загружать вершины из внешнего JSON-файла или редактора уровней
- Динамически изменять вершины тела во время выполнения, создавая "деформируемые" объекты
- Комбинировать несколько простых тел (
fromVerts) в одно составное (compound body) для ещё более сложных конструкций
