SpriteKit Project — AbsolutelyBrickingIt — Part 10: Add a game over scene

atomicswiftdev
App Dev Pro Tips
Published in
3 min readAug 21, 2024

In this article, we’ll show a game over screen when the ball goes out of bounds.

Add image assets

Drag the images needed for the game over scene into the Assets file in Xcode:

Add game over image assets

Add the game over scene

Add a new Swift file called GameOverScene to the project. Add sprite nodes to the scene in the didMove(to view:_) method as usual:

import SpriteKit

class GameOverScene: SKScene {

override func didMove(to view: SKView) {
let backgroundNode = SKSpriteNode(imageNamed: "background.menu")
backgroundNode.position = CGPoint(x: 0.5 * size.width, y: 0.5 * size.height)
addChild(backgroundNode)

let gameOverNode = SKSpriteNode(imageNamed: "text.game-over")
gameOverNode.position = CGPoint(x: 0.5 * size.width, y: 0.75 * size.height)
addChild(gameOverNode)

let menuNode = SKSpriteNode(imageNamed: "button.menu")
menuNode.position = CGPoint(x: 0.5 * size.width, y: 0.32 * size.height)
addChild(menuNode)

let playNode = SKSpriteNode(imageNamed: "button.play-again")
playNode.position = CGPoint(x: 0.5 * size.width, y: 0.2 * size.height)
addChild(playNode)
}
}

Use a coordinator to handle button taps

We can use a coordinator for the game over scene to pass handling of the button taps back to GameViewController, just like we have done with all the other scenes so far:

protocol GameOverSceneCoordinator: AnyObject {
func gameOverSceneMenuTapped(_ scene: GameOverScene)
func gameOverScenePlayTapped(_ scene: GameOverScene)
}

class GameOverScene: SKScene {

weak var coordinator: GameOverSceneCoordinator?

private var menuNode: SKSpriteNode?
private var playNode: SKSpriteNode?

override func didMove(to view: SKView) {
..

addChild(menuNode)
self.menuNode = menuNode

..
addChild(playNode)
self.playNode = playNode
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let point = touch.location(in: self)

if playNode?.contains(point) == true {
coordinator?.gameOverScenePlayTapped(self)
} else if menuNode?.contains(point) == true {
coordinator?.gameOverSceneMenuTapped(self)
}
}
}
}

Note that references to the menu and play button nodes are kept to handle touches on them.

Add the game over scene to GameViewController

GameViewController will implement the coordinator methods for the game over scene, presenting the menu scene and the game scene when the corresponding button is tapped:

extension GameViewController: GameOverSceneCoordinator {

func gameOverSceneMenuTapped(_ scene: GameOverScene) {
present(scene: menuScene)
}

func gameOverScenePlayTapped(_ scene: GameOverScene) {
present(scene: gameScene)
}
}

Finally, we can replace the console output from before and present the game over scene in the coordinator implementation for handling the game scene’s game over event:

private extension GameViewController {
...

var gameOverScene: GameOverScene {
let scene = GameOverScene(size: sceneSize)
scene.coordinator = self
scene.scaleMode = .resizeFill
return scene
}
}

extension GameViewController: GameSceneCoordinator {

func gameSceneGameEnded(_ scene: GameScene) {
present(scene: gameOverScene)
}
}

Now we have a game over scene that is presented when the game ends due to the ball going out of bounds. The user can choose to return to the menu or play again from this screen:

Simulator showing game over scene

Code

This article corresponds to the merge commit Add game over scene (#10) in the GitHub repository AbsolutelyBrickingIt

Next Part

Part 11: Add the first brick

--

--