Step 10 - Game Over
For our game, when the bird collides with the ground, pipe, or goes offscreen we want to trigger a game over. To accomplish this we'll setup a start()
, stop()
and reset()
on the various components of our game so that we can "freeze" things in place on a game over.
We implement a showStartInstructions()
method that shows our start game label and starts the game as soon as a pointer is tapped.
We'll show the start instructions at the beginning and on a game over.
(Remember to remove or comment out the line this.pipeFactory.start();
so that the PipeFactory
does not start before displaying the start instructions)
typescript
// level.tsexport class Level extends ex.Scene {...startGameLabel = new ex.Label({text: 'Tap to Start',x: 200,y: 200,z: 2,font: new ex.Font({size: 30,color: ex.Color.White,textAlign: ex.TextAlign.Center})});override onInitialize(engine: ex.Engine): void {...//this.pipeFactory.start();this.showStartInstructions();}showStartInstructions() {this.startGameLabel.graphics.isVisible = true;this.engine.input.pointers.once('down', () => {this.reset();this.startGameLabel.graphics.isVisible = false;this.bird.start();this.pipeFactory.start();this.ground.start();});}reset() {this.bird.reset();this.pipeFactory.reset();this.score = 0;this.scoreLabel.text = `Score: ${this.score}`;}triggerGameOver() {this.pipeFactory.stop();this.bird.stop();this.ground.stop();this.showStartInstructions();}}
typescript
// level.tsexport class Level extends ex.Scene {...startGameLabel = new ex.Label({text: 'Tap to Start',x: 200,y: 200,z: 2,font: new ex.Font({size: 30,color: ex.Color.White,textAlign: ex.TextAlign.Center})});override onInitialize(engine: ex.Engine): void {...//this.pipeFactory.start();this.showStartInstructions();}showStartInstructions() {this.startGameLabel.graphics.isVisible = true;this.engine.input.pointers.once('down', () => {this.reset();this.startGameLabel.graphics.isVisible = false;this.bird.start();this.pipeFactory.start();this.ground.start();});}reset() {this.bird.reset();this.pipeFactory.reset();this.score = 0;this.scoreLabel.text = `Score: ${this.score}`;}triggerGameOver() {this.pipeFactory.stop();this.bird.stop();this.ground.stop();this.showStartInstructions();}}
In our Bird
we want to trigger this game over when it leaves the screen and when it collides with a Pipe
or the Ground
typescript
// bird.tsexport class Bird extends ex.Actor {playing = false;...override onInitialize(): void {...this.on('exitviewport', () => {this.level.triggerGameOver();});}override onPostUpdate(engine: ex.Engine): void {if (!this.playing) return;...}start() {this.playing = true;this.pos = Config.BirdStartPos; // starting positionthis.acc = ex.vec(0, Config.BirdAcceleration); // pixels per second per second}reset() {this.pos = Config.BirdStartPos; // starting positionthis.stop();}stop() {this.playing = false;this.vel = ex.vec(0, 0);this.acc = ex.vec(0, 0);}override onCollisionStart(_self: ex.Collider, other: ex.Collider): void {if (other.owner instanceof Pipe ||other.owner instanceof Ground) {this.level.triggerGameOver();}}}
typescript
// bird.tsexport class Bird extends ex.Actor {playing = false;...override onInitialize(): void {...this.on('exitviewport', () => {this.level.triggerGameOver();});}override onPostUpdate(engine: ex.Engine): void {if (!this.playing) return;...}start() {this.playing = true;this.pos = Config.BirdStartPos; // starting positionthis.acc = ex.vec(0, Config.BirdAcceleration); // pixels per second per second}reset() {this.pos = Config.BirdStartPos; // starting positionthis.stop();}stop() {this.playing = false;this.vel = ex.vec(0, 0);this.acc = ex.vec(0, 0);}override onCollisionStart(_self: ex.Collider, other: ex.Collider): void {if (other.owner instanceof Pipe ||other.owner instanceof Ground) {this.level.triggerGameOver();}}}