О чем этот пример
При создании классических аркадных игр, таких как «Астероиды», часто возникает задача сделать так, чтобы объекты, вылетев за границу экрана, появлялись с противоположной стороны. В физическом движке Matter.js для Phaser эта задача решается элегантно с помощью свойства `wrapBounds`. В этой статье мы разберем пример, который создает множество сталкивающихся фигур, автоматически телепортирующихся в заданных границах. Этот подход избавляет от необходимости вручную проверять позицию каждого объекта и идеально подходит для симуляции замкнутого игрового пространства.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
// Let's create a bunch of random shaped objects and add them to the world
for (let i = 0; i < 48; i++)
{
const x = Phaser.Math.Between(100, 700);
const y = Phaser.Math.Between(100, 500);
const wrapBounds = {
min: {
x: 0,
y: 0
},
max: {
x: 800,
y: 600
}
};
if (Math.random() < 0.7)
{
const sides = Phaser.Math.Between(3, 14);
const radius = Phaser.Math.Between(8, 50);
this.matter.add.polygon(x, y, sides, radius, { restitution: 0.9, wrapBounds: wrapBounds });
}
else
{
const width = Phaser.Math.Between(16, 128);
const height = Phaser.Math.Between(8, 64);
this.matter.add.rectangle(x, y, width, height, { restitution: 0.9, wrapBounds: wrapBounds });
}
}
this.matter.add.mouseSpring();
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#000000',
parent: 'phaser-example',
physics: {
default: 'matter',
matter: {
gravity: {
x: 0.05,
y: 0.1
},
debug: true
}
},
scene: Example
};
const game = new Phaser.Game(config);
Настройка физики и сцены
Вся конфигурация игры происходит в объекте config. Ключевой момент — активация физического движка Matter.js с небольшой гравитацией и включенным режимом отладки. Это позволяет видеть хитбоксы объектов.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#000000',
parent: 'phaser-example',
physics: {
default: 'matter',
matter: {
gravity: { x: 0.05, y: 0.1 }, // Легкая диагональная гравитация
debug: true // Показывать контуры тел
}
},
scene: Example
};
Определение границ телепортации
Сердце примера — объект wrapBounds. Он определяет прямоугольную область, за пределы которой объекты не могут вылететь. Вместо этого они моментально переносятся на противоположную сторону этой области. В нашем случае границы совпадают с размерами игрового холста (800x600), начиная с точки (0,0). Этот объект будет передан в свойствах каждому создаваемому физическому телу.
const wrapBounds = {
min: { x: 0, y: 0 },
max: { x: 800, y: 600 }
};
Создание случайных фигур
В методе create() в цикле генерируется 48 объектов. Для каждого сначала определяется случайная позиция в пределах экрана с помощью Phaser.Math.Between. Затем, с вероятностью 70%, создается многоугольник (polygon), а в остальных 30% случаев — прямоугольник (rectangle). Оба метода принимают координаты, размеры и объект с настройками тела.
if (Math.random() < 0.7) {
const sides = Phaser.Math.Between(3, 14);
const radius = Phaser.Math.Between(8, 50);
this.matter.add.polygon(x, y, sides, radius, { restitution: 0.9, wrapBounds: wrapBounds });
} else {
const width = Phaser.Math.Between(16, 128);
const height = Phaser.Math.Between(8, 64);
this.matter.add.rectangle(x, y, width, height, { restitution: 0.9, wrapBounds: wrapBounds });
}
Важные параметры в настройках:
* restitution: 0.9 — задает высокий коэффициент упругости (отскок), делая столкновения более «живыми».
* wrapBounds: wrapBounds — применяет ранее объявленные границы телепортации к этому конкретному телу.
Добавление интерактивности
В конце метода create() добавляется интерактивный элемент — мышиная пружина. Вызов this.matter.add.mouseSpring() позволяет игроку кликать и перетаскивать любые физические объекты на сцене, чтобы наблюдать за их взаимодействием и эффектом телепортации в действии. Это полезно для тестирования и создания прототипов.
this.matter.add.mouseSpring();
Что попробовать дальше
Свойство wrapBounds в Matter.js — это мощный и простой инструмент для создания эффекта «завернутого» мира. Оно полностью управляется движком, освобождая разработчика от написания рутинных проверок позиции. Для экспериментов попробуйте изменить размеры wrapBounds, чтобы область телепортации была меньше или больше экрана. Или примените разные границы к разным группам объектов, создав несколько независимых «зон телепортации» на одной сцене. Это может стать основой для интересных игровых механик.
