Phaser 3(游戏框架):collider回调被调用,但somethimes对象仍然穿过其他对象,而不是碰撞
Phaser 3 (Game framework): collider callback is called, but somethimes object still passes through other object, instead of colliding
我正在制作一个小型 flappy-bird-like-game 演示。一切似乎都很好,但我有一个小 problem/question.
我设置了一个 collider
函数,回调按预期工作,当“两个”对象发生碰撞时,但有一个奇怪的行为:
- 白色方块(小鸟)从侧面过来时可以飞越障碍物
- 但从下面或上面来时不能通过
但是回调总是执行。
蓝色箭头标记正方形通过的地方
绿色箭头标记方块未通过的地方
我不确定这是不是因为我使用的矩形 (它们有时) 会导致问题,或者因为我的嵌套物理设置。 我什至尝试用精灵替换白色矩形,但这仍然产生相同的结果 result/error。
For my demo: I could probablly just destroy the object and restart the level on collision, but I still would like to understand why this is happening? And how I can prevent this, inconsistant behavior.
I'm probably missing something, but couldn't find it, and I don't want to rebuild the application again.
所以我的问题是:为什么会这样?我该如何防止这种情况?
代码如下:
const width = 400;
const height = 200;
const spacing = width / 4;
const levelSpeed = width / 4;
const flySpeed = width / 4;
var GameScene = {
create (){
let player = this.add.rectangle(width / 4, height / 2, 20, 20, 0xffffff);
this.physics.add.existing(player);
this.input.keyboard.on('keydown-SPACE', (event) => {
if(player.body.velocity.y >= -flySpeed/2){
player.body.setVelocityY(-flySpeed);
}
});
player.body.onWorldBounds = true;
player.body.setCollideWorldBounds(true );
this.physics.world.on("worldbounds", function (body) {
console.info('GAME OVER');
player.y = height / 2;
player.body.setVelocity(0);
});
this.pipes = [];
for(let idx = 1; idx <= 10; idx++) {
let obstacle = this.createObstacle(spacing * idx, Phaser.Math.Between(-height/3, 0));
this.add.existing(obstacle);
this.pipes.push(obstacle);
this.physics.add.collider(obstacle.list[0], player)
this.physics.add.collider(obstacle.list[1], player, _ => console.info(2))
}
},
update(){
this.pipes.forEach((item) => {
if(item.x <= 0){
item.body.x = spacing * 10;
}
})
},
extend: {
createObstacle (x, y){
let topPipe = (new Phaser.GameObjects.Rectangle(this, 0, 0 , 20 , height / 2 ,0xff0000)).setOrigin(0);
let bottomPipe = (new Phaser.GameObjects.Rectangle(this, 0, height/2 + 75, 20 , height / 2 ,0xff0000)).setOrigin(0);
this.physics.add.existing(topPipe);
this.physics.add.existing(bottomPipe);
topPipe.body.setImmovable(true);
topPipe.body.allowGravity = false;
bottomPipe.body.setImmovable(true);
bottomPipe.body.allowGravity = false;
let obstacle = new Phaser.GameObjects.Container(this, x, y, [
topPipe,
bottomPipe
]);
this.physics.add.existing(obstacle);
obstacle.body.velocity.x = - levelSpeed;
obstacle.body.allowGravity = false;
return obstacle;
}
}
};
var config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width,
height,
scene: [GameScene],
physics: {
default: 'arcade',
arcade: {
gravity: { y: flySpeed },
debug: true
},
}
};
var game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
目前我只能假设,当物理对象嵌套时,物理对象似乎无法正常工作。
也许我错了, 但是因为我在没有 nested physics - objects 的情况下再次重写了代码并且它似乎工作,我认为我的假设是正确的。 我不应该过度设计我的代码。
If someone has more insides, please let me know/share. I still not 100% sure, if this is the real reason, for the strange behavior.
重写代码:
const width = 400;
const height = 200;
const spacing = width / 4;
const levelSpeed = width / 4;
const flySpeed = width / 4;
var GameScene = {
create (){
let player = this.add.rectangle(width / 4, height / 2, 20, 20, 0xffffff);
this.physics.add.existing(player);
this.input.keyboard.on('keydown-SPACE', (event) => {
if(player.body.velocity.y >= -flySpeed/2){
player.body.setVelocityY(-flySpeed);
}
});
player.body.onWorldBounds = true;
player.body.setCollideWorldBounds(true );
this.physics.world.on("worldbounds", function (body) {
console.info('GAME OVER');
player.x = width / 4;
player.y = height / 2;
player.body.setVelocity(0);
});
this.pipes = [];
for(let idx = 1; idx <= 10; idx++) {
let obstacle = this.createObstacle(spacing * idx, Phaser.Math.Between(-height/3, 0));
this.add.existing(obstacle[0]);
this.add.existing(obstacle[1]);
this.pipes.push(...obstacle);
this.physics.add.collider(obstacle[0], player)
this.physics.add.collider(obstacle[1], player, _ => console.info(2))
}
},
update(){
this.pipes.forEach((item) => {
if(item.x <= 0){
item.body.x = spacing * 10;
}
item.body.velocity.x = - levelSpeed;
})
},
extend: {
createObstacle (x, y){
let topPipe = (new Phaser.GameObjects.Rectangle(this, x, -20 , 20 , height / 2 ,0xff0000)).setOrigin(0);
let bottomPipe = (new Phaser.GameObjects.Rectangle(this, x, height/2 + 75, 20 , height / 2 ,0xff0000)).setOrigin(0);
this.physics.add.existing(topPipe);
this.physics.add.existing(bottomPipe);
topPipe.body.setImmovable(true);
topPipe.body.allowGravity = false;
topPipe.body.velocity.x = - levelSpeed;
bottomPipe.body.setImmovable(true);
bottomPipe.body.allowGravity = false;
bottomPipe.body.velocity.x = - levelSpeed;
return [topPipe, bottomPipe];
}
}
};
var config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width,
height,
scene: [GameScene],
physics: {
default: 'arcade',
arcade: {
gravity: { y: flySpeed },
debug: true
},
}
};
var game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
我正在制作一个小型 flappy-bird-like-game 演示。一切似乎都很好,但我有一个小 problem/question.
我设置了一个 collider
函数,回调按预期工作,当“两个”对象发生碰撞时,但有一个奇怪的行为:
- 白色方块(小鸟)从侧面过来时可以飞越障碍物
- 但从下面或上面来时不能通过
但是回调总是执行。
蓝色箭头标记正方形通过的地方
绿色箭头标记方块未通过的地方
我不确定这是不是因为我使用的矩形 (它们有时) 会导致问题,或者因为我的嵌套物理设置。 我什至尝试用精灵替换白色矩形,但这仍然产生相同的结果 result/error。
For my demo: I could probablly just destroy the object and restart the level on collision, but I still would like to understand why this is happening? And how I can prevent this, inconsistant behavior.
I'm probably missing something, but couldn't find it, and I don't want to rebuild the application again.
所以我的问题是:为什么会这样?我该如何防止这种情况?
代码如下:
const width = 400;
const height = 200;
const spacing = width / 4;
const levelSpeed = width / 4;
const flySpeed = width / 4;
var GameScene = {
create (){
let player = this.add.rectangle(width / 4, height / 2, 20, 20, 0xffffff);
this.physics.add.existing(player);
this.input.keyboard.on('keydown-SPACE', (event) => {
if(player.body.velocity.y >= -flySpeed/2){
player.body.setVelocityY(-flySpeed);
}
});
player.body.onWorldBounds = true;
player.body.setCollideWorldBounds(true );
this.physics.world.on("worldbounds", function (body) {
console.info('GAME OVER');
player.y = height / 2;
player.body.setVelocity(0);
});
this.pipes = [];
for(let idx = 1; idx <= 10; idx++) {
let obstacle = this.createObstacle(spacing * idx, Phaser.Math.Between(-height/3, 0));
this.add.existing(obstacle);
this.pipes.push(obstacle);
this.physics.add.collider(obstacle.list[0], player)
this.physics.add.collider(obstacle.list[1], player, _ => console.info(2))
}
},
update(){
this.pipes.forEach((item) => {
if(item.x <= 0){
item.body.x = spacing * 10;
}
})
},
extend: {
createObstacle (x, y){
let topPipe = (new Phaser.GameObjects.Rectangle(this, 0, 0 , 20 , height / 2 ,0xff0000)).setOrigin(0);
let bottomPipe = (new Phaser.GameObjects.Rectangle(this, 0, height/2 + 75, 20 , height / 2 ,0xff0000)).setOrigin(0);
this.physics.add.existing(topPipe);
this.physics.add.existing(bottomPipe);
topPipe.body.setImmovable(true);
topPipe.body.allowGravity = false;
bottomPipe.body.setImmovable(true);
bottomPipe.body.allowGravity = false;
let obstacle = new Phaser.GameObjects.Container(this, x, y, [
topPipe,
bottomPipe
]);
this.physics.add.existing(obstacle);
obstacle.body.velocity.x = - levelSpeed;
obstacle.body.allowGravity = false;
return obstacle;
}
}
};
var config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width,
height,
scene: [GameScene],
physics: {
default: 'arcade',
arcade: {
gravity: { y: flySpeed },
debug: true
},
}
};
var game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>
目前我只能假设,当物理对象嵌套时,物理对象似乎无法正常工作。
也许我错了, 但是因为我在没有 nested physics - objects 的情况下再次重写了代码并且它似乎工作,我认为我的假设是正确的。 我不应该过度设计我的代码。
If someone has more insides, please let me know/share. I still not 100% sure, if this is the real reason, for the strange behavior.
重写代码:
const width = 400;
const height = 200;
const spacing = width / 4;
const levelSpeed = width / 4;
const flySpeed = width / 4;
var GameScene = {
create (){
let player = this.add.rectangle(width / 4, height / 2, 20, 20, 0xffffff);
this.physics.add.existing(player);
this.input.keyboard.on('keydown-SPACE', (event) => {
if(player.body.velocity.y >= -flySpeed/2){
player.body.setVelocityY(-flySpeed);
}
});
player.body.onWorldBounds = true;
player.body.setCollideWorldBounds(true );
this.physics.world.on("worldbounds", function (body) {
console.info('GAME OVER');
player.x = width / 4;
player.y = height / 2;
player.body.setVelocity(0);
});
this.pipes = [];
for(let idx = 1; idx <= 10; idx++) {
let obstacle = this.createObstacle(spacing * idx, Phaser.Math.Between(-height/3, 0));
this.add.existing(obstacle[0]);
this.add.existing(obstacle[1]);
this.pipes.push(...obstacle);
this.physics.add.collider(obstacle[0], player)
this.physics.add.collider(obstacle[1], player, _ => console.info(2))
}
},
update(){
this.pipes.forEach((item) => {
if(item.x <= 0){
item.body.x = spacing * 10;
}
item.body.velocity.x = - levelSpeed;
})
},
extend: {
createObstacle (x, y){
let topPipe = (new Phaser.GameObjects.Rectangle(this, x, -20 , 20 , height / 2 ,0xff0000)).setOrigin(0);
let bottomPipe = (new Phaser.GameObjects.Rectangle(this, x, height/2 + 75, 20 , height / 2 ,0xff0000)).setOrigin(0);
this.physics.add.existing(topPipe);
this.physics.add.existing(bottomPipe);
topPipe.body.setImmovable(true);
topPipe.body.allowGravity = false;
topPipe.body.velocity.x = - levelSpeed;
bottomPipe.body.setImmovable(true);
bottomPipe.body.allowGravity = false;
bottomPipe.body.velocity.x = - levelSpeed;
return [topPipe, bottomPipe];
}
}
};
var config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width,
height,
scene: [GameScene],
physics: {
default: 'arcade',
arcade: {
gravity: { y: flySpeed },
debug: true
},
}
};
var game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser@3.55.2/dist/phaser.js"></script>