在 Phaser 3 中如何使用带有 tilemap 的物质物理引擎来防止玩家跳墙
How do you prevent player from jumping up walls using the matter physics engine with a tilemap in Phaser 3
我正在尝试使用物质物理引擎在 Phaser 3 中创建一个平台游戏,目前我正在尝试使用平铺创建关卡,我已经到了玩家无法无限跳跃但他们仍然可以跳起来的地步墙。
我目前正在尝试做到这一点,以便它们只有在与称为地板的特定层发生碰撞时才能跳跃。
当我尝试使用下面的代码时,我收到一条错误消息:
未捕获的类型错误:无法设置 null 的属性(设置 'label')
game.js(创建函数):
create() {
//External function to create player
player(this,'test',300,200,'player')
pawn.setScale(1.5)
pawn.setDepth(2)
pawn.setBounce(0.1)
pawn.setFriction(0,0,1)
pawn.setCircle(20)
pawn.setMass(1)
this.touchingGround = false;
this.jumpForce = 0.05
this.map = this.make.tilemap({key: 'lv3'})
this.tileset = this.map.addTilesetImage('tiles','tile', 32, 32)
this.walls = this.map.createLayer('walls', this.tileset)
this.walls.setCollisionByExclusion(-1, true);
this.floor = this.map.createLayer('floor', this.tileset)
this.floor.setCollisionByExclusion(-1, true);
this.matter.world.convertTilemapLayer(this.walls);
this.matter.world.convertTilemapLayer(this.floor);
pawn.body.label = 'player'
this.floor.body.label = 'floor'
this.matter.world.on("collisionactive", (e,o1, o2) => {
if(o1.label == 'player' && o2.label == 'floor')
{
this.touchingGround = true;
}
});
};
抱歉,如果这是一个非常简单的修复,或者只是行不通,我太蠢了。
我不是 matter.js 引擎专家,但我认为错误发生在 this.floor.body.label = 'floor'
行。一个简单的解决方案是使用 convertTilemapLayer
方法 (Documentation) 中的 options
参数。
这是一个有效的演示:
(代码基于此 phaser.io example )
var config = {
type: Phaser.AUTO,
width: 11 * 16,
height: 6 * 16,
zoom: 2,
pixelArt: true,
scene: {
preload: preload,
create: create
},
physics: {
default: 'matter',
matter: {
gravity: {
y:.3
},
}
},
banner: false
};
function preload (){
this.load.image('mario-tiles', 'https://labs.phaser.io/assets/tilemaps/tiles/super-mario.png');
}
function create (){
var level = [
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 14, 14, 14, 14, 14, 0, 0, 0, 0 ],
]
var map = this.make.tilemap({ data: level, tileWidth: 16, tileHeight: 16 });
var tiles = map.addTilesetImage('mario-tiles');
var layer = map.createLayer(0, tiles, 0, 0);
let player = this.add.rectangle(40, 10, 8, 8, 0xffffff)
layer.setCollision([14]);
this.matter.add.gameObject(player);
this.matter.world.convertTilemapLayer(layer, {label:'floor'});
let info = this.add.text(4, 4, 'Waiting for collision', {color:'#ffffff', fontSize:10})
.setOrigin(0);
player.body.label = 'player';
this.matter.world.on("collisionactive", (e, o1, o2) => {
if(o1.label == 'player' && o2.label == 'floor') {
info.setText('touching');
}
});
}
new Phaser.Game(config);
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
我正在尝试使用物质物理引擎在 Phaser 3 中创建一个平台游戏,目前我正在尝试使用平铺创建关卡,我已经到了玩家无法无限跳跃但他们仍然可以跳起来的地步墙。
我目前正在尝试做到这一点,以便它们只有在与称为地板的特定层发生碰撞时才能跳跃。
当我尝试使用下面的代码时,我收到一条错误消息:
未捕获的类型错误:无法设置 null 的属性(设置 'label')
game.js(创建函数):
create() {
//External function to create player
player(this,'test',300,200,'player')
pawn.setScale(1.5)
pawn.setDepth(2)
pawn.setBounce(0.1)
pawn.setFriction(0,0,1)
pawn.setCircle(20)
pawn.setMass(1)
this.touchingGround = false;
this.jumpForce = 0.05
this.map = this.make.tilemap({key: 'lv3'})
this.tileset = this.map.addTilesetImage('tiles','tile', 32, 32)
this.walls = this.map.createLayer('walls', this.tileset)
this.walls.setCollisionByExclusion(-1, true);
this.floor = this.map.createLayer('floor', this.tileset)
this.floor.setCollisionByExclusion(-1, true);
this.matter.world.convertTilemapLayer(this.walls);
this.matter.world.convertTilemapLayer(this.floor);
pawn.body.label = 'player'
this.floor.body.label = 'floor'
this.matter.world.on("collisionactive", (e,o1, o2) => {
if(o1.label == 'player' && o2.label == 'floor')
{
this.touchingGround = true;
}
});
};
抱歉,如果这是一个非常简单的修复,或者只是行不通,我太蠢了。
我不是 matter.js 引擎专家,但我认为错误发生在 this.floor.body.label = 'floor'
行。一个简单的解决方案是使用 convertTilemapLayer
方法 (Documentation) 中的 options
参数。
这是一个有效的演示:
(代码基于此 phaser.io example )
var config = {
type: Phaser.AUTO,
width: 11 * 16,
height: 6 * 16,
zoom: 2,
pixelArt: true,
scene: {
preload: preload,
create: create
},
physics: {
default: 'matter',
matter: {
gravity: {
y:.3
},
}
},
banner: false
};
function preload (){
this.load.image('mario-tiles', 'https://labs.phaser.io/assets/tilemaps/tiles/super-mario.png');
}
function create (){
var level = [
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 14, 14, 14, 14, 14, 0, 0, 0, 0 ],
]
var map = this.make.tilemap({ data: level, tileWidth: 16, tileHeight: 16 });
var tiles = map.addTilesetImage('mario-tiles');
var layer = map.createLayer(0, tiles, 0, 0);
let player = this.add.rectangle(40, 10, 8, 8, 0xffffff)
layer.setCollision([14]);
this.matter.add.gameObject(player);
this.matter.world.convertTilemapLayer(layer, {label:'floor'});
let info = this.add.text(4, 4, 'Waiting for collision', {color:'#ffffff', fontSize:10})
.setOrigin(0);
player.body.label = 'player';
this.matter.world.on("collisionactive", (e, o1, o2) => {
if(o1.label == 'player' && o2.label == 'floor') {
info.setText('touching');
}
});
}
new Phaser.Game(config);
<script src="//cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>