О чем этот пример
Создание игрового мира с препятствиями — ключевая задача для любого разработчика. В Phaser Arcade Physics для этого используются простые, но мощные методы `collider` и `overlap`. В этой статье мы разберем, как загружать тайловую карту, настраивать столкновения и реагировать на взаимодействия между спрайтом и тайлами. Вы научитесь управлять физическими взаимодействиями в вашей игре, используя стандартный пример из документации Phaser.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
cursors;
player;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.tilemapTiledJSON('map', 'assets/tilemaps/maps/tile_properties.json');
this.load.image('tiles', 'assets/tilemaps/tiles/gridtiles.png');
this.load.image('ball', 'assets/sprites/orb-blue.png');
}
create ()
{
const map = this.make.tilemap({ key: 'map' });
const tileset = map.addTilesetImage('tiles');
const layer = map.createLayer('Tile Layer 1', tileset, 0, 0);
map.setCollision([ 34, 20 ]); // 20 = dark gray, 32 = dark blue
// map.setCollision([ 136 ]); // dark brown
// map.setCollision([ 80 ]); // yellow
// map.setCollision([ 122 ]); // light brown
this.player = this.physics.add.sprite(48, 48, 'ball');
this.physics.add.collider(this.player, layer);
// this.physics.add.collider(player, layer, () => {
// console.log('colliding');
// });
// this.physics.add.overlap(player, layer, () => {
// console.log('overlapping');
// });
this.cursors = this.input.keyboard.createCursorKeys();
}
update (time, delta)
{
this.player.setVelocity(0);
// Horizontal movement
if (this.cursors.left.isDown)
{
this.player.setVelocityX(-100);
}
else if (this.cursors.right.isDown)
{
this.player.setVelocityX(100);
}
// Vertical movement
if (this.cursors.up.isDown)
{
this.player.setVelocityY(-100);
}
else if (this.cursors.down.isDown)
{
this.player.setVelocityY(100);
}
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'phaser-example',
physics: {
default: 'arcade',
arcade: {
gravity: { y: 0 }
}
},
scene: Example
};
const game = new Phaser.Game(config);
Подготовка карты и слоя
Перед настройкой физики необходимо создать сам мир. В методе preload загружаются ресурсы: JSON-файл карты, созданной в Tiled, изображение с тайлами и спрайт игрока.
В методе create происходит основная инициализация. Сначала создается объект тайловой карты, затем к ней добавляется набор тайлов (tileset) и, наконец, визуальный слой.
const map = this.make.tilemap({ key: 'map' });
const tileset = map.addTilesetImage('tiles');
const layer = map.createLayer('Tile Layer 1', tileset, 0, 0);
Настройка столкновений для тайлов
Не все тайлы на карте должны быть препятствиями. Метод setCollision позволяет указать, с какими индексами тайлов будет происходить физическое столкновение. Индексы соответствуют номерам тайлов в tileset.
В примере изначально активны столкновения с тайлами 34 и 20. Закомментированные строки показывают, как можно быстро переключать, какие тайлы являются твердыми.
map.setCollision([ 34, 20 ]); // 20 = dark gray, 32 = dark blue
// map.setCollision([ 136 ]); // dark brown
// map.setCollision([ 80 ]); // yellow
// map.setCollision([ 122 ]); // light brown
Создание игрока и физического взаимодействия
Игрок создается как физический спрайт с помощью this.physics.add.sprite. После этого необходимо определить, как он будет взаимодействовать со слоем тайлов. Phaser Arcade Physics предлагает два основных метода:
1. `this.physics.add.collider` — объекты будут сталкиваться и отталкиваться друг от друга.
2. `this.physics.add.overlap` — объекты будут физически проходить друг сквозь друга, но мы сможем зафиксировать факт их перекрытия.
В примере по умолчанию используется коллайдер, который обеспечивает классическое поведение стены.
this.player = this.physics.add.sprite(48, 48, 'ball');
this.physics.add.collider(this.player, layer);
Разница между Collider и Overlap
В закомментированном коде примера показаны оба варианта с callback-функциями. Это ключевой момент для геймдизайна.
* **Коллайдер с callback**: Вызовется в момент столкновения и *остановки* объекта. Подходит для нанесения урона при ударе, звука удара. * **Оверлап с callback**: Вызовется, когда хитбоксы объектов начинают пересекаться, и будет вызываться постоянно, пока они пересекаются. Идеален для зон, наносящих периодический урон, сбора предметов или активации ловушек.
// При столкновении
this.physics.add.collider(player, layer, () => {
console.log('colliding');
});
// При перекрытии (нахождении в одной области)
this.physics.add.overlap(player, layer, () => {
console.log('overlapping');
});
Управление движением игрока
Чтобы игрок мог сталкиваться с тайлами, им нужно управлять. В методе update каждый кадр сначала обнуляется скорость, чтобы движение было отзывчивым и прекращалось при отпускании клавиши. Затем проверяется состояние клавиш-стрелок и устанавливается соответствующая скорость по осям X и Y.
this.player.setVelocity(0);
if (this.cursors.left.isDown) { this.player.setVelocityX(-100); }
else if (this.cursors.right.isDown) { this.player.setVelocityX(100); }
if (this.cursors.up.isDown) { this.player.setVelocityY(-100); }
else if (this.cursors.down.isDown) { this.player.setVelocityY(100); }
Что попробовать дальше
Используя setCollision, collider и overlap, вы можете быстро создавать сложные игровые миры с физикой. Для экспериментов попробуйте
- Активировать разные наборы тайлов для столкновений
- Заменить
colliderнаoverlapи реализовать зону, которая наносит урон при нахождении в ней - Добавить в callback-функцию
overlapизменение цвета спрайта игрока, пока он находится на "опасном" тайле
