О чем этот пример
В Phaser контейнеры (Container) позволяют группировать игровые объекты и работать с ними как с единым целым. Но что, если этому целому нужна реалистичная физика? В этом примере мы совместим мощь физического движка Matter.js с удобством контейнеров, а также реализуем плавное слежение камеры за составным объектом. Это полезно для создания сложных игровых сущностей, состоящих из нескольких спрайтов, которые должны взаимодействовать с миром по законам физики.
Версия 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('platform', 'assets/sprites/platform.png');
this.load.image('mushroom', 'assets/sprites/mushroom2.png');
}
create ()
{
const worldWidth = 1600;
const worldHeight = 1200;
this.matter.world.setBounds(0, 0, worldWidth, worldHeight);
const image1 = this.add.image(0, -30, 'mushroom');
const image2 = this.add.image(-40, 30, 'mushroom');
const image3 = this.add.image(40, 30, 'mushroom');
const container = this.add.container(100, 100, [ image1, image2, image3 ]);
// A Container has a default size of 0x0, so we need to give it a size before enabling a physics body
container.setSize(128, 64);
this.cameras.main.startFollow(container);
const physicsContainer = this.matter.add.gameObject(container);
physicsContainer.setFrictionAir(0.001);
physicsContainer.setBounce(1);
this.matter.add.image(350, 450, 'platform', null, { isStatic: true }).setScale(6, 0.5).setAngle(10);
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#1b1464',
parent: 'phaser-example',
physics: {
default: 'matter',
matter: {
debug: true,
gravity: {
y: 0.3
}
}
},
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и загрузка ассетов
В методе preload мы загружаем два изображения: платформу и гриб. Обратите внимание на использование setBaseURL для указания базового пути, что упрощает загрузку ресурсов из удаленного хранилища.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('platform', 'assets/sprites/platform.png');
this.load.image('mushroom', 'assets/sprites/mushroom2.png');
}
Создание составного объекта в контейнере
В create мы сначала задаем размер физического мира больше, чем размер экрана, чтобы объекты могли свободно перемещаться. Затем создаем три отдельных изображения гриба с разными координатами относительно точки (0,0).
const image1 = this.add.image(0, -30, 'mushroom');
const image2 = this.add.image(-40, 30, 'mushroom');
const image3 = this.add.image(40, 30, 'mushroom');
Эти три изображения объединяются в контейнер. Первые два аргумента this.add.container(100, 100, ...) задают мировые координаты самого контейнера.
const container = this.add.container(100, 100, [ image1, image2, image3 ]);
**Важный момент:** у контейнера по умолчанию нулевой размер (0x0). Для корректной работы физического тела ему необходимо задать размер.
container.setSize(128, 64);
Добавление физики и настройка камеры
Превращаем обычный контейнер в физический игровой объект с помощью this.matter.add.gameObject(). Это ключевой метод, который добавляет тело Matter.js к существующему объекту Phaser.
const physicsContainer = this.matter.add.gameObject(container);
Настраиваем свойства физического тела: очень низкое сопротивление воздуха для плавного скольжения и упругость (bounce), равную 1, для идеально упругих столкновений.
physicsContainer.setFrictionAir(0.001);
physicsContainer.setBounce(1);
Чтобы камера автоматически следовала за нашим контейнером, используем метод startFollow.
this.cameras.main.startFollow(container);
Создание статичной платформы
Добавляем в мир статичную платформу, от которой будет отскакивать наш контейнер. Параметр { isStatic: true } делает тело неподвижным. Методами setScale и setAngle мы растягиваем платформу и задаем ей небольшой угол наклона.
this.matter.add.image(350, 450, 'platform', null, { isStatic: true }).setScale(6, 0.5).setAngle(10);
Конфигурация игры и физики
В конфигурации игры критически важно правильно настроить физический плагин Matter. Мы задаем его как систему по умолчанию, включаем отладочную визуалицию (debug: true) и устанавливаем слабую вертикальную гравитацию.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#1b1464',
parent: 'phaser-example',
physics: {
default: 'matter', // Активация Matter.js
matter: {
debug: true, // Показывать контуры тел
gravity: {
y: 0.3 // Слабая гравитация
}
}
},
scene: Example
};
Что попробовать дальше
Этот пример демонстрирует мощную комбинацию: контейнеры для логической группировки спрайтов и Matter.js для добавления к этой группе сложной физики. Теперь вы можете создавать составные игровые объекты (например, машины из деталей, персонажей с инвентарем), которые реалистично взаимодействуют с окружением. Для экспериментов попробуйте: изменить форму физического тела контейнера с помощью setBody, добавить в контейнер другие типы объектов (текст, частицы), изменить параметры слежения камеры или создать цепную реакцию столкновений нескольких физических контейнеров.
