物理引擎让一切变得简单多了——我们只需要添加两行简单的代码。首先,在你的 update() 方法中添加一行新的代码,用于检测球与砖块之间的碰撞,如下所示:
class ExampleScene extends Phaser.Scene {
// ...
update() {
this.physics.collide(this.ball, this.paddle);
this.physics.collide(this.ball, this.bricks, (ball, brick) =>
this.hitBrick(ball, brick),
);
this.paddle.x = this.input.x || this.scale.width * 0.5;
// ...
}
// ...
}
球的位置将与组中所有砖块的位置进行比较。第三个可选参数是发生碰撞时执行的函数。Phaser 会用两个参数调用此函数——第一个参数是球,我们已经显式地将其传递给了 collide 方法,第二个参数是球正在碰撞的砖块组中的单个砖块。在这里,我们在一个名为 hitBrick() 的方法中实现此行为。在 ExampleScene 类末尾,紧靠结束大括号 } 之前,添加此新方法,如下所示:
class ExampleScene extends Phaser.Scene {
// ...
hitBrick(ball, brick) {
brick.destroy();
}
}
就这样!重新加载你的代码,你应该可以看到新的碰撞检测按要求正常工作了。
当你使用纯 JavaScript 时,你可能会期望编写更多自己的计算来实现碰撞检测。这就是使用框架的好处——你可以把很多繁琐的代码交给 Phaser 来处理,而专注于制作游戏中最有趣、最吸引人的部分。
这是您到目前为止应该看到的效果,实时运行。要查看其源代码,请单击“播放”按钮。
<script src="https://cdnjs.cloudflare.com/ajax/libs/phaser/3.90.0/phaser.js"></script>
* {
padding: 0;
margin: 0;
}
class ExampleScene extends Phaser.Scene {
ball;
paddle;
bricks;
preload() {
this.load.setBaseURL(
"https://mdn.github.io/shared-assets/images/examples/2D_breakout_game_Phaser",
);
this.load.image("ball", "ball.png");
this.load.image("paddle", "paddle.png");
this.load.image("brick", "brick.png");
}
create() {
this.physics.world.checkCollision.down = false;
this.ball = this.add.sprite(
this.scale.width * 0.5,
this.scale.height - 25,
"ball",
);
this.physics.add.existing(this.ball);
this.ball.body.setVelocity(150, -150);
this.ball.body.setCollideWorldBounds(true, 1, 1);
this.ball.body.setBounce(1);
this.paddle = this.add.sprite(
this.scale.width * 0.5,
this.scale.height - 5,
"paddle",
);
this.paddle.setOrigin(0.5, 1);
this.physics.add.existing(this.paddle);
this.paddle.body.setImmovable(true);
this.initBricks();
}
update() {
this.physics.collide(this.ball, this.paddle);
this.physics.collide(this.ball, this.bricks, (ball, brick) =>
this.hitBrick(ball, brick),
);
this.paddle.x = this.input.x || this.scale.width * 0.5;
const ballIsOutOfBounds = !Phaser.Geom.Rectangle.Overlaps(
this.physics.world.bounds,
this.ball.getBounds(),
);
if (ballIsOutOfBounds) {
// Game over logic
location.reload();
}
}
initBricks() {
const bricksLayout = {
width: 50,
height: 20,
count: {
row: 3,
col: 7,
},
offset: {
top: 50,
left: 60,
},
padding: 10,
};
this.bricks = this.add.group();
for (let c = 0; c < bricksLayout.count.col; c++) {
for (let r = 0; r < bricksLayout.count.row; r++) {
const brickX =
c * (bricksLayout.width + bricksLayout.padding) +
bricksLayout.offset.left;
const brickY =
r * (bricksLayout.height + bricksLayout.padding) +
bricksLayout.offset.top;
const newBrick = this.add.sprite(brickX, brickY, "brick");
this.physics.add.existing(newBrick);
newBrick.body.setImmovable(true);
this.bricks.add(newBrick);
}
}
}
hitBrick(ball, brick) {
brick.destroy();
}
}
const config = {
type: Phaser.CANVAS,
width: 480,
height: 320,
scene: ExampleScene,
scale: {
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH,
},
backgroundColor: "#eeeeee",
physics: {
default: "arcade",
},
};
const game = new Phaser.Game(config);
我们可以击中砖块并将其移除,这是对现有游戏玩法的不错补充。如果能计算被摧毁的砖块并相应地增加分数,那就更好了。