О чем этот пример
В Arcade Physics движке Phaser по умолчанию все тела считаются прямоугольными. Но что происходит, когда вы превращаете спрайт в круг с помощью `setCircle`? Этот пример наглядно демонстрирует важное и не всегда очевидное поведение: круги с включенной физикой по умолчанию становятся "проталкиваемыми" (pushable). Статья разберет этот нюанс, покажет, как им управлять, и объяснит, почему это критично для геймдизайна, особенно в играх с толканием объектов или персонажей.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
var config = {
type: Phaser.AUTO,
width: 864,
height: 632,
parent: 'phaser-example',
backgroundColor: '#2d2d2d',
physics: {
default: 'arcade',
arcade: {
gravity: { y: 0 },
debug: true
}
},
scene: {
preload: preload,
create: create,
update: update,
}
};
var game = new Phaser.Game(config);
function preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.setPath('assets/sprites');
this.load.image('blockANP');
this.load.image('blockBNP');
this.load.image('blockAP');
this.load.image('blockBP');
}
var cursors
var active
function create ()
{
this.physics.world.setBounds(0, 0, 864, 632);
cursors = this.input.keyboard.createCursorKeys();
var left = this.physics.add.image(200, 196-16, 'blockANP').setCollideWorldBounds().setInteractive();
var right = this.physics.add.image(600, 196-16, 'blockBNP').setCollideWorldBounds().setInteractive();
var leftRect = this.physics.add.image(400, 196-16, 'blockANP').setCollideWorldBounds().setInteractive();
var t = this.add.text(10, 10, 'Click to take control');
window.left = left;
window.right = right;
window.rect = leftRect;
// left.setBounce(0.5);
// right.setBounce(0.5);
// If either one of these are a circle they will get pushed.
left.setCircle(32);
right.setCircle(32);
active = left;
left.on('pointerdown', () => {
active = left;
t.setText('Moving left circle');
});
right.on('pointerdown', () => {
active = right;
t.setText('Moving right circle');
});
leftRect.on('pointerdown', () => {
active = leftRect;
t.setText('Moving leftRect');
});
// left.setPushable(false);
// right.setPushable(false);
// leftRect.setPushable(false);
if (left.body.pushable)
{
left.setTexture('blockAP');
}
if (right.body.pushable)
{
right.setTexture('blockBP');
}
if (leftRect.body.pushable)
{
leftRect.setTexture('blockAP');
}
this.physics.add.collider(left, right);
this.physics.add.collider(leftRect, right);
}
function update ()
{
if (cursors.left.isDown)
{
active.setVelocityX(-160);
}
else if (cursors.right.isDown)
{
active.setVelocityX(160);
}
else if (cursors.up.isDown)
{
active.setVelocityY(-160);
}
else if (cursors.down.isDown)
{
active.setVelocityY(160);
}
else {
active.setVelocity(0)
}
}
Суть примера: управление pushable-свойством
В этом примере создаются три физических тела: два круга и один прямоугольник. По умолчанию в Arcade Physics тело, созданное через this.physics.add.image, имеет свойство body.pushable равное true. Однако, ключевая деталь: **для тел, чья форма задана как прямоугольник (дефолтная), это свойство игнорируется.** Они не будут сдвигаться при столкновении с другими движущимися телами. Всё меняется, когда вы вызываете .setCircle() — теперь тело становится кругом, и свойство pushable вступает в силу.
Вы можете переключать управление между объектами кликом мыши и двигать активный объект стрелками. Круги будут сталкиваться и толкать друг друга, а прямоугольник — нет, если только вы явно не измените это поведение.
Пример также визуализирует состояние pushable: спрайты, которые могут быть протолкнуты, отображаются текстурами с буквой 'P' (Pushable).
Настройка сцены и создание тел
В create() функции инициализируется физический мир и создаются интерактивные объекты. Обратите внимание, как задаются круги и проверяется их свойство pushable.
// Создаем три физических тела
var left = this.physics.add.image(200, 196-16, 'blockANP').setCollideWorldBounds().setInteractive();
var right = this.physics.add.image(600, 196-16, 'blockBNP').setCollideWorldBounds().setInteractive();
var leftRect = this.physics.add.image(400, 196-16, 'blockANP').setCollideWorldBounds().setInteractive();
// Превращаем два тела в круги радиусом 32 пикселя
left.setCircle(32);
right.setCircle(32);
// Проверяем и визуализируем свойство pushable
if (left.body.pushable)
{
left.setTexture('blockAP');
}
Коллайдеры регистрируются для всех комбинаций кругов и прямоугольника, чтобы между ними работало обнаружение столкновений.
this.physics.add.collider(left, right);
this.physics.add.collider(leftRect, right);
Как управлять проталкиваемостью
Свойством pushable можно управлять напрямую. Если вы хотите, чтобы круг (или любое другое тело) не сдвигался при столкновении, установите для него setPushable(false). Это полезно для создания статических препятствий сложной формы или "тяжелых" объектов.
// Делаем круг непроталкиваемым, как стену
left.setPushable(false);
// Возвращаем возможность быть протолкнутым
left.setPushable(true);
Важно: вызов setPushable(false) для тела, которое всё ещё является прямоугольником (не вызывали setCircle), не окажет никакого видимого эффекта на столкновения, так как прямоугольники и так не толкаются по умолчанию. Изменение текстуры на основе body.pushable в примере как раз помогает отследить этот момент.
Практические сценарии использования
1. **Головоломки с толканием ящиков:** Сделайте ящики кругами (setCircle) с pushable=true, а стенки прямоугольниками или кругами с pushable=false. Это создаст чёткую физику.
2. **Система веса:** Комбинируйте pushable и массу тела (body.mass), чтобы более лёгкие объекты толкались сильнее, чем тяжёлые.
3. **Динамические изменения:** Меняйте pushable во время игры. Например, объект можно толкать, пока он не "активируется", после чего он становится неподвижным (setPushable(false)).
4. **Отладка:** Включите debug: true в конфиге физики, чтобы видеть реальные hitbox'ы (круги или прямоугольники). Это поможет избежать путаницы, какая форма и свойство сейчас активны.
// Пример конфигурации физики с отладкой
physics: {
default: 'arcade',
arcade: {
gravity: { y: 0 },
debug: true // Визуализирует формы тел
}
}
Что попробовать дальше
Понимание различий между прямоугольными и круглыми телами в Arcade Physics — ключ к предсказуемой физике в вашей игре. Круги по умолчанию "реагируют" на свойство pushable, что открывает возможности для сложных взаимодействий. Поэкспериментируйте: создайте сцену, где некоторые круги можно толкать, а другие — нет; попробуйте динамически менять форму тела с setCircle на setSize (вернув прямоугольник) и наблюдайте за изменением поведения. Это даст вам полный контроль над тем, как объекты сталкиваются и взаимодействуют в игровом мире.
