How to Make a Line Drawing Game with Sprite Kit and Swift

Learn how to make a Line Drawing Game like Flight Control with Sprite Kit and Swift! By Jean-Pierre Distler.

Leave a rating/review
Save for later
Share
You are currently viewing page 6 of 6 of this article. Click here to view the first page.

Game Over: When Pigs Collide

When two pigs collide, the game will show a “Game Over!” message and then give the player the chance to start a new round.

Open GameScene.swift and add a BOOL variable to indicate when the game is over:

var gameOver = false

You don't want the pigs moving or spawning when the game is over, so wrap the current contents of update() inside an if statement, as follows:

if !gameOver {
  // existing code here
}

Also, add the following code at the beginning of spawnAnimal to make sure new pigs don’t appear after the player has lost:

if gameOver {
  return
}

Now add this method, which you'll call when two pigs collide:

func handleAnimalCollision() {
  gameOver = true
        
  let gameOverLabel = SKLabelNode(fontNamed: "Thonburi-Bold")
  gameOverLabel.text = "Game Over!"
  gameOverLabel.name = "label"
  gameOverLabel.fontSize = 35.0
  gameOverLabel.position = CGPointMake(size.width / 2.0, size.height / 2.0 + 20.0)
  gameOverLabel.zPosition = 5
        
  let tapLabel = SKLabelNode(fontNamed: "Thonburi-Bold")
  tapLabel.text = "Tap to restart."
  tapLabel.name = "label"
  tapLabel.fontSize = 25.0
  tapLabel.position = CGPointMake(size.width / 2.0, size.height / 2.0 - 20.0)
  tapLabel.zPosition = 5
      
  addChild(gameOverLabel)
  addChild(tapLabel)
}

Here you first set gameOver to true, which ends the game. You add two labels centered on the screen telling the user that the game is over and that they can tap the screen to restart. You set each label's zPosition to five to ensure they are in front of all other nodes.

Now call this new method in didBeganContact(). Replace the NSLog statement that logs “Animal collision detected” with the following line:

handleAnimalCollision()

You told the player that they can tap the screen to restart, but right now that isn't true. Add the following method to GameScene.swift to handle restarting:

func restartGame() {
  enumerateChildNodesWithName("line", usingBlock: {node, stop in
    node.removeFromParent()
  })
        
  enumerateChildNodesWithName("pig", usingBlock: {node, stop in
    node.removeFromParent()
  })
  
  enumerateChildNodesWithName("label", usingBlock: {node, stop in
    node.removeFromParent()
  })
        
  currentSpawnTime = 5.0
  gameOver = false
  spawnAnimal()
}

restartGame() removes all lines, pigs and labels from the scene, sets the spawn time back to five seconds, sets gameOver to false and begins spawning animals.

You need to call this method if the user taps the screen while the game is over, so add the following lines to the top of touchesBegan(_:,withEvent:):

if gameOver {
  restartGame()
}

All right, then! Build and run once more, and enjoy the line drawing game you created. See if you’re a natural-born swineherd.

Game_Over

Adding Polish

You may have noticed some places where the game behaves strangely. For example, look at the behavior of spawning pigs—they appear to walk in place! You can fix this easily by calling moveRandom on the pigs when you spawn them.

Inside GameScene.swift, call this method in spawnAnimal, just after the line that adds the pig to the scene:

pig.moveRandom()

Build and run, and now the pigs move right away:

EagerPigs

Now let’s take a closer look at the way your game currently handles touches. Run the app and add a path to a pig, but before the pig arrives at the endpoint, try to change the path by drawing a new one.

As you can see, the pig initially ignores your second command and continues along the first path. Then, after reaching the end point, it moves back to the place where you tried to change direction and follows the second path. Every new path is just tacked onto the old one!

It would be much better if the game replaced the old path with a new path. To make this happen, first open Pig.swift and add a new method:

func clearWayPoints() {
  wayPoints.removeAll(keepCapacity: false)
}

This method simply removes all objects from wayPoints.

Now go to GameScene.swift and add the following line to touchesBegan(_:,withEvent:), just above the line that calls addMovingPoint():

pig.clearWayPoints()

You call clearWayPoints() every time the player touches a pig.

Build and run, and now the pigs listen to your every command!

ListeningPigs

Challenge: Add a HUD to the scene showing the player how many pigs they have removed. See if you can accomplish this by yourself before checking the tips below.
[spoiler title="Tips"]

  • Add an variable named animalCount inside GameScene. You'll want to increment it every time you remove a pig, but because the logic to remove the pig is in Pig.swift, you should add a new method to GameScene, perhaps named pigRemoved, and call it from checkForHome in Pig.swift.
  • Add an SKLabelNode to your scene. Be sure to set its zPosition to a value above the other nodes. Take a look at the other labels you added for hints. For easy access to the label, you should hold a reference to it—maybe in an variable named hud?
  • Update the text of your hud whenever you update animalCount.
  • Don't forget to reset the counter when you restart the game.

[/spoiler]

Where to Go From Here?

Here is the final project with all the code from the above tutorial.

There is still a lot of room for improvement in your game. But that’s OK—it gives you plenty of opportunities to practice your skills, old and new!

  • You could reduce the area searched when removing waypoints, which would make the pig look like it was on top of the line rather than having the line always just out of the pig's reach.
  • If you move your finger slowly while creating a line, it currently adds far too many points, producing an unpleasant visual experience. You could apply a smoothing algorithm to the points, such as the basic one described here, to reduce redundant points and improve the quality of both the line rendering and the pig's motion.
  • It's currently possible for a new pig to spawn with no warning right on top of an existing pig, ending the game immediately. How would you fix this problem?
  • You could add an indicator to warn the player of incoming pigs.
  • You could add different levels that you load from a plist, as well as different animals.
  • You could use the additional trough images provided with the starter project to make the trough appear empty after a certain amount of feeding, and require the player to refill the trough by tapping on it.
  • To tell you the truth, I really don't know why the game should end when two animals collide. It would be funnier if the animals began running in random directions for a short time after a collision. Because everything must come to an end (this tutorial, too) you could add a counter that ends the game after five collisions.

Whether or not you implement any of these suggestions, I'm sure you have your own excellent ideas, and now you know more of what you need to bring them to the App Store. Make sure to drop me a note when your game is available.

If you want to learn more about creating games like this, check out our book iOS Games by Tutorials. We’ll teach you everything you need to know – from physics, to tile maps, to particle systems, and even how to make your games “juicy” with polish and special effects.

If you have any questions or comments about this tutorial, please join the discussion below!