О чем этот пример
Сенсоры — это особый тип физических тел, которые могут обнаруживать столкновения, но не участвуют в физическом взаимодействии. Это открывает широкие возможности для создания триггерных зон, областей поражения, детекторов подбора предметов и невидимых активаторов событий в вашей игре. В этой статье мы разберем пример из официальной документации Phaser, где игрок в виде сенсора может "проходить" сквозь платформы, но при этом менять их цвет при контакте. Вы узнаете, как создать сенсор, настроить обработку событий коллизий и управлять таким объектом.
Версия 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('block', 'assets/sprites/block.png');
this.load.image('platform', 'assets/sprites/platform.png');
}
create ()
{
this.matter.add.image(400, 150, 'platform').setStatic(true);
this.matter.add.image(600, 350, 'platform').setStatic(true);
this.matter.add.image(200, 550, 'platform').setStatic(true);
this.player = this.matter.add.image(200, 300, 'block', null, { isSensor: true });
this.matter.world.on('collisionstart', (event, bodyA, bodyB) =>
{
bodyA.gameObject.setTint(0xff0000);
});
this.matter.world.on('collisionend', (event, bodyA, bodyB) =>
{
bodyA.gameObject.setTint(0xffffff);
});
this.cursors = this.input.keyboard.createCursorKeys();
this.add.text(10, 10, 'Move with cursor keys. Hit blocks with sensors.', { font: '16px Courier', fill: '#ffffff' });
}
update ()
{
if (this.cursors.left.isDown)
{
this.player.setVelocityX(-10);
}
else if (this.cursors.right.isDown)
{
this.player.setVelocityX(10);
}
else
{
this.player.setVelocityX(0);
}
if (this.cursors.up.isDown)
{
this.player.setVelocityY(-10);
}
else if (this.cursors.down.isDown)
{
this.player.setVelocityY(10);
}
else
{
this.player.setVelocityY(0);
}
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#1b1464',
parent: 'phaser-example',
physics: {
default: 'matter',
matter: {
debug: true,
gravity: {
y: 0
}
}
},
scene: Example
};
const game = new Phaser.Game(config);
Настройка физики Matter.js
Вся работа с сенсорами ведется через плагин Matter.js. Первым делом необходимо правильно инициализировать физический движок в конфигурации игры.
Мы отключаем гравитацию по оси Y, чтобы упростить управление объектом с клавиатуры, и включаем режим отладки debug: true, который визуализирует физические тела.
physics: {
default: 'matter',
matter: {
debug: true,
gravity: {
y: 0
}
}
}
Создание статических платформ и сенсора
В методе create() сцены создаются статические платформы и главный объект — игрок. Ключевое отличие в создании игрока — пятый параметр, объект дополнительных настроек Matter тела { isSensor: true }.
Свойство isSensor: true сообщает движку, что это тело должно только регистрировать пересечения (коллизии), но не оказывать и не получать физического ответа (отталкивание, трение). Платформы же создаются как обычные статические тела. Метод setStatic(true) делает тело неподвижным.
this.matter.add.image(400, 150, 'platform').setStatic(true);
this.matter.add.image(600, 350, 'platform').setStatic(true);
this.matter.add.image(200, 550, 'platform').setStatic(true);
this.player = this.matter.add.image(200, 300, 'block', null, { isSensor: true });
Обработка событий коллизий
Для реакции на пересечение сенсора с другими телами Matter.js предоставляет события collisionstart и collisionend. Они срабатывают на уровне мира this.matter.world.
В обработчике события collisionstart тело bodyA (которое является телом нашего игрока-сенсора) получает ссылку на свой игровой объект (gameObject), и этому объекту устанавливается красный оттенок. Когда коллизия заканчивается (collisionend), оттенок сбрасывается на белый.
Важно: в этом примере сенсор всегда передается как bodyA. В реальном проекте нужно проверять, какое из столкнувшихся тел является сенсором.
this.matter.world.on('collisionstart', (event, bodyA, bodyB) =>
{
bodyA.gameObject.setTint(0xff0000);
});
this.matter.world.on('collisionend', (event, bodyA, bodyB) =>
{
bodyA.gameObject.setTint(0xffffff);
});
Управление сенсором
Поскольку сенсор не сталкивается с окружением, управлять им можно, напрямую задавая скорость. В методе update() мы проверяем состояние клавиш-стрелок и с помощью setVelocityX() и setVelocityY() устанавливаем соответствующую скорость для тела игрока.
Если ни одна клавиша не нажата, скорость сбрасывается до нуля, что останавливает объект.
if (this.cursors.left.isDown)
{
this.player.setVelocityX(-10);
}
else if (this.cursors.right.isDown)
{
this.player.setVelocityX(10);
}
else
{
this.player.setVelocityX(0);
}
// ... аналогично для оси Y
Что попробовать дальше
Сенсоры в Matter.js — мощный инструмент для создания логики игры, не связанной напрямую с физикой столкновений. Вы можете использовать их для зон финиша, ловушек, диалоговых триггеров или областей, наносящих периодический урон. Для экспериментов попробуйте сделать сенсор не кругом, а сложной полигональной формой, создать несколько сенсоров с разными реакциями или использовать событие collisionactive для непрерывного действия (например, медленного отнимания здоровья) пока объект находится в зоне.
