О чем этот пример
При создании игр часто нужно не просто сталкивать объекты, а запускать событие при их пересечении: сбор монет, нанесение урона, активацию ловушек. Встроенный метод `overlap()` в Arcade Physics решает эту задачу без физического отталкивания объектов. Эта статья разберет пример, где движущийся спрайт взаимодействует с группой статичных объектов, меняя цвет при контакте. Вы научитесь настраивать детектор перекрытия и визуализировать его состояние в реальном времени.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
group;
sprite;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('mushroom', 'assets/sprites/mushroom2.png');
this.load.image('ball', 'assets/sprites/shinyball.png');
}
create ()
{
this.sprite = this.physics.add.image(400, 300, 'mushroom')
.setVelocity(100, 200)
.setBounce(1, 1)
.setCollideWorldBounds(true)
.setGravityY(200);
this.group = this.physics.add.staticGroup({
key: 'ball',
frameQuantity: 30
});
Phaser.Actions.PlaceOnRectangle(this.group.getChildren(), new Phaser.Geom.Rectangle(84, 84, 616, 416));
this.group.refresh();
this.physics.add.overlap(this.sprite, this.group);
}
update ()
{
this.sprite.body.debugBodyColor = this.sprite.body.touching.none ? 0x0099ff : 0xff9900;
}
}
const config = {
type: Phaser.AUTO,
antialias: false,
width: 800,
height: 600,
parent: 'phaser-example',
physics: {
default: 'arcade',
arcade: {debug: true}
},
scene: Example
};
const game = new Phaser.Game(config);
Настройка сцены и загрузка ресурсов
В классе сцены объявляются два свойства: group для статичных объектов и sprite для движущегося спрайта. В методе preload() загружаются два изображения, которые будут использоваться как текстуры.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('mushroom', 'assets/sprites/mushroom2.png');
this.load.image('ball', 'assets/sprites/shinyball.png');
}
Создание физических тел и группы
В create() создается основной спрайт с физическим телом. Он получает начальную скорость, отскок от границ мира, гравитацию и возможность сталкиваться с краями холста. Это типичная настройка для динамического объекта.
this.sprite = this.physics.add.image(400, 300, 'mushroom')
.setVelocity(100, 200)
.setBounce(1, 1)
.setCollideWorldBounds(true)
.setGravityY(200);
Затем создается статичная группа (staticGroup). Статичные тела не двигаются под действием физики, но могут участвовать в обнаружении столкновений. Здесь группа инициализируется с 30 одинаковыми спрайтами.
this.group = this.physics.add.staticGroup({
key: 'ball',
frameQuantity: 30
});
Расположение объектов и настройка overlap
Спрайты из группы размещаются по периметру прямоугольника с помощью утилиты Phaser.Actions.PlaceOnRectangle. После изменения позиции статичных тел необходимо вызвать refresh() для обновления их физических границ (AABB).
Phaser.Actions.PlaceOnRectangle(this.group.getChildren(), new Phaser.Geom.Rectangle(84, 84, 616, 416));
this.group.refresh();
Ключевая строка — создание детектора перекрытия между спрайтом и группой. Метод this.physics.add.overlap() начинает проверять пересечение их тел каждый кадр, но без физической реакции (объекты не отталкиваются).
this.physics.add.overlap(this.sprite, this.group);
Визуальная индикация контакта
В методе update(), который выполняется каждый кадр, меняется цвет отладки физического тела спрайта. Свойство body.touching.none равно true, если тело ни с чем не контактирует в текущем кадре. В зависимости от этого выбирается синий (0x0099ff) или оранжевый (0xff9900) цвет.
update ()
{
this.sprite.body.debugBodyColor = this.sprite.body.touching.none ? 0x0099ff : 0xff9900;
}
Важно: эта визуализация работает только при включенной отладке физики в конфигурации игры (arcade: {debug: true}).
Конфигурация игры и физики
В объекте конфигурации активируется Arcade Physics как система по умолчанию. Параметр debug: true позволяет видеть границы физических тел, что необходимо для работы визуальной индикации из update().
const config = {
type: Phaser.AUTO,
antialias: false,
width: 800,
height: 600,
parent: 'phaser-example',
physics: {
default: 'arcade',
arcade: {debug: true}
},
scene: Example
};
Что попробовать дальше
Метод overlap() — это легковесный инструмент для событийного программирования, когда физическое столкновение не требуется. Он идеально подходит для триггеров, сбора предметов или зон поражения. Для экспериментов попробуйте добавить коллбэк-функцию третьим аргументом в overlap(), чтобы выполнять код при каждом контакте, или используйте collider() вместо overlap(), чтобы объекты отталкивались друг от друга.
