Create a SpriteKit Game Project


Lay Out the Game UI


Define the Game Piece Model


Create the Level Model


Draw the Rune Sprites


Detecting Taps on Runes


Determine Swipe Direction


Add Physics to Shatter Runes


Build Out the UI Text


Keeping Score


Displaying Score Feedback


Create a SpriteKit Game Project

Published by Chris Slowik

Episode Notes

Extra tips from the author

What is SpriteKit?

Have you ever wanted to make a game for iOS but didn't really know where to start? Heard of SpriteKit but not really sure how it all goes together? Through this series we're going to start from scratch with a cool rune-smashing game based on swipes and taps. It's a simple one-hand interaction with a scoring twist. Lets get started!

Create a Game project

Open Xcode, and create a new project. Select the Game preset, and you'll be creating a SpriteKit template project. Call it Runes, or RuneChute, or whatever sounds excellent to you! Pick your team settings and set the language to Swift if it's not automatically. Save the project where you like, and when it opens you can uncheck both landscape options on the project settings. We won't want the phone to rotate to landscape!

Grab the images from the source files, or make your own based on the UI shown in the video! Drag all the images in the Images source folder into Images.xcassets. The sprites for the runes and smashed pieces of runes, as well as some other features, are contained in the Sprites.atlas folder. This looks like a normal folder in the finder, but when you drag it into the Project Navigator and import it into your project, Xcode will recognize it as a sprite atlas. When it builds the project, this will become an atlas with the corresponding location data attached - you don't have to do anything. The plus side to this also is that the images remain separate files in your Finder.

Lay Some Groundwork

We won't need the template files that come with the Game project, so delete the .sks files - these are for using the visual built-in editor and we're not building anything using that. Now, edit the contents of GameViewController and start with this general boilerplate:

import UIKit
import SpriteKit

class GameViewController: UIViewController {
    // MARK: - Behavior
    override var shouldAutorotate: Bool {
        return true
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return [.portrait, .portraitUpsideDown]
    override var prefersStatusBarHidden: Bool {
        return true

    // MARK: - Lifecycle
    override func viewDidLoad() {

In the Behavior section above, we set up the general app settings regarding rotation and what orientations are supported. Ensuring the status bar is hidden is important for a game as well! The Lifecycle section is where most of the game view controller code will go for now. Right after super.viewDidLoad(), create the SceneKit View and make sure multitouch is disabled.

let skView = view as! SKView
skView.isMultipleTouchEnabled = false

Then, set up the Game Scene, with a size that matches the wood background image. This image is set up to match the aspect ratio of the iPhone 7/8 for 1x and 2x. This covers the sizing for iPhone. The 3x image is set up with a taller aspect ratio to match the iPhone X. This image will work for the iPhone Plus and iPhone X. We'll set the scaleMode of the scene to .aspectFill so it fills the screen but crops if it doesn't fit - this is how the additional graphics for iPhone X will work! Finally, you can present the scene. Here's what the code looks like so far:

override func viewDidLoad() {

    let skView = view as! SKView
    skView.isMultipleTouchEnabled = false

    scene = GameScene(size: UIImage(named:"woodBG").size)
    scene.scaleMode = .aspectFill


Building the Background

Move over to the GameScene and clear out the pre-written code except for the class declaration and the SpriteKit import. The first thing to do is override a couple inits from SKScene. We won't use init coder at all, so we can just toss a fatal error in there to crash the app if somehow it happens. (It won't). All our work will happen in init size:

required init?(coder aDecoder: NSCoder) {
    fatalError("init coder not implemented")

override init(size: CGSize) {
    super.init(size: size)

Under the super init call, we'll set the anchor point of the scene to the center. This will help when we are working with the rune column and other things. Add a bg image, set it to the size of the scene (remember we already set the scene to the wood BG size, so this should match!), and add that to the scene.

anchorPoint = CGPoint(x: 0.5, y: 0.5)

let bg = SKSpriteNode(imageNamed: "woodBG")
bg = size

Next will be to draw the column walls and the gutter for the chips to slide down. We'll create three new sprites, one for each image. The walls will have their anchor points set to their edges for ease of positioning. The gutter is just centered, so we don't even need to change the position. Add the sprites as children of the scene, and run the app. You should see the game background drawn on screen!

let leftWall = SKSpriteNode(imageNamed: "leftWall")
let rightWall = SKSpriteNode(imageNamed: "rightWall")
let gutter = SKSpriteNode(imageNamed: "columnBG")
leftWall.anchorPoint = CGPoint(x: 0.0, y: 0.5)
rightWall.anchorPoint = CGPoint(x: 1.0, y: 0.5)
leftWall.position = CGPoint(x: -size.width / 2, y: 0.0)
rightWall.position = CGPoint(x: size.width / 2, y: 0.0)
Episode Topics: