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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
How to Make a Line Drawing Game with Sprite Kit and Swift
55 mins
- Getting Started
- Adding the Background… and a Pig!
- Moving the Sprite
- Responding to Touches
- Drawing Lines
- Continuous Movement
- Rotating the Sprite
- Animating the Sprite
- Your Gameplay Strategy
- Completing the Scene
- Spawning Pigs
- Detecting Collisions
- Adding Physics Bodies
- Feeding the Pigs
- Finishing the Game
- Game Over: When Pigs Collide
- Adding Polish
- Where to Go From Here?
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.
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:
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!
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
insideGameScene
. 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 toGameScene
, perhaps namedpigRemoved
, and call it fromcheckForHome
in Pig.swift. - Add an
SKLabelNode
to your scene. Be sure to set itszPosition
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 namedhud
? - Update the text of your
hud
whenever you updateanimalCount
. - 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!