物理引擎讓一切變得簡單多了——我們只需要新增兩行簡單的程式碼。首先,在你的 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);
我們可以擊中磚塊並將其移除,這是對現有遊戲玩法的不錯補充。如果能計算被摧毀的磚塊並相應地增加分數,那就更好了。