Win the game
{{PreviousNext("Games/Tutorials/2D_breakout_game_Phaser/The_score", "Games/Tutorials/2D_breakout_game_Phaser/Extra_lives")}}
This is the 12th step out of 16 of the Gamedev Phaser tutorial. Implementing winning in our game is quite easy: if you happen to destroy all the bricks, then you win.
How to win?
Add the following new code into your update()
method:
class ExampleScene extends Phaser.Scene {
// ...
update() {
// ...
if (this.bricks.countActive() === 0) {
alert("You won the game, congratulations!");
location.reload();
}
}
// ...
}
We count the number of bricks that are still alive, using the countAlive()
method on this.bricks
. If there are no more bricks left alive, then we display the winning message, restarting the game once the alert is dismissed.
Compare your code
Here’s what you should have so far, running live. To view its source code, click the “Play” button.
<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;
scoreText;
score = 0;
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();
this.scoreText = this.add.text(5, 5, "Points: 0", {
font: "18px Arial",
color: "#0095dd",
});
}
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();
}
if (this.bricks.countActive() === 0) {
alert("You won the game, congratulations!");
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();
this.score += 10;
this.scoreText.setText(`Points: ${this.score}`);
}
}
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);
{{EmbedLiveSample("compare your code", "", 480, , , , , "allow-modals")}}
Next steps
Both losing and winning are implemented, so the core gameplay of our game is finished. Now let’s add something extra—we’ll give the player three lives instead of one.
{{PreviousNext("Games/Tutorials/2D_breakout_game_Phaser/The_score", "Games/Tutorials/2D_breakout_game_Phaser/Extra_lives")}}