SpriteKit Swift 3 Tutorial for Beginners

Ray Wenderlich

SpriteKit Swift 3 Tutorial for Beginners
Note from Ray: This is a Swift 3 and iOS 10 update to a popular tutorial on our site, released as part of the iOS 10 Feast.

Like Batman and Robin or Superman and Lois Lane, SpriteKit and Swift are an amazing combination:

  • SpriteKit is one of the best ways to make games on iOS. It’s easy to learn, powerful, and is fully-supported by Apple.
  • Swift is an easy language to get started with, especially if you are a beginner to the iOS platform.

In this tutorial, you will learn how to create a simple 2D game using Apple’s 2D game framework, SpriteKit – using Swift!

You can either follow along with this tutorial, or just jump straight to the sample project at the end. And yes. There will be ninjas.

Note: This tutorial has a special place in my heart, as the original version was one of the first tutorials ever released on our site. It was written in a completely different language (Objective-C) and a completely different game framework (Cocos2D). My, how times have changed! :]

SpriteKit vs. Unity

The most popular alternative to SpriteKit at the moment is a game framework called Unity. Unity was originally developed as a 3D engine, but it recently got full built-in 2D support too.

So before you get started, I recommend you put some thought into whether SpriteKit or Unity is the best choice for your game.

Advantages of SpriteKit

  • It’s built right into iOS. There is no need to download extra libraries or have external dependencies. You can also seamlessly use other iOS APIs like iAd, In-App Purchases, etc. without having to rely on extra plugins.
  • It leverages your existing skills. If you already know Swift and iOS development, you can pick up SpriteKit extremely quickly.
  • It’s written by Apple. This gives you some confidence that it will be well supported moving forward on all of Apple’s new products. For example, you can use the same SpriteKit code to make your game work on iOS, OS X, and tvOS without a hitch.
  • It’s free. Maybe one of the best reasons for small indies! You get all of SpriteKit’s functionality at no cost. Unity does have a free version but does not have all of the features of the Pro version (you’ll need to upgrade if you want to avoid the Unity splash screen, for example).

Advantages of Unity

  • Cross-platform. This is one of the big ones. If you use SpriteKit, you’re locked into the Apple ecosystem. With Unity, you can easily port your games to Android, Windows, and more.
  • Visual scene designer. Unity makes it extremely easy to lay out your levels and test your game in realtime with the click of a button. SpriteKit does have a very basic scene editor, but it is very basic compared to what Unity offers.
  • Asset store. Unity comes with a built-in asset store where you can buy various components for your game. Some of these components can save you a good bit of development time!
  • More powerful. In general, Unity just has more features and functionality than the SpriteKit / Scene Kit combination.

Which Should I Choose?

After this a lot of you may be thinking, “Well, which 2D framework should I choose?”

The answer that depends on what your goals are. Here’s my 2c:

  • If you are a complete beginner, or solely focused on the Apple ecosystem: Use SpriteKit – it’s built in, easy to learn, and will get the job done.
  • If you’re want to be cross-platform, or have a more complicated game: Use Unity – it’s more powerful and flexible.

If you think Unity is for you, check out some of our our brand new book Unity Games by Tutorials.

Otherwise, keep reading on to get started with SpriteKit!

Hello, SpriteKit!

Let’s start by getting a simple Hello World project up and running by using the SpriteKit Game template that comes built in to Xcode 8.

Start up Xcode, select File\New\Project, choose the iOS\Application\Game template, and click Next:


Enter SpriteKitSimpleGame for the Product Name, Swift for Language, SpriteKit for Game Technology, iPhone for Devices, and click Next:


Choose somewhere on your drive to save the project, and click Create. Select your iPhone 7 simulator, then click the play button to run the project as-is. After a brief splash screen, a Hello World screen should appear – try dragging your mouse to make some spinning rectangles appear:


SpriteKit is organized into the concept of scenes, which are kind of like “levels’ or “screens” for a game. For example, you might have a scene for the main gameplay area, and another scene for the world map between levels.

If you take a look at your project, you’ll see the template has already created a scene for you by default – GameScene. Open GameScene.swift and you’ll see that it contains some code to make the rectangles spin.

In this tutorial, you’ll mainly be working within GameScene. But before you begin, you have to make a few tweaks because this game needs to run in landscape instead of portrait.

Initial Setup

The template provided to you has two issues. First, it’s set up the game to be Portrait, but you want landscape. Second, it is currently using SpriteKit’s scene editor, which you don’t need for this tutorial. Let’s fix these issues.

First, open your target setting by clicking your SpriteKitSimpleGame project in the Project Navigator, selecting the SpriteKitSimpleGame target. Then, in the Deployment Info section, uncheck Portrait so only Landscape Left and Landscape Right are checked. Also click the Requires full screen checkbox, as shown below:


Second, delete GameScene.sks and Actions.sks and choose Move to Trash when prompted. These files allows you to lay out sprites and other components of a scene visually, however for this game it’s just easier to create things programmatically, so you don’t need it.

Next, open GameViewController.swift and replace the contents with the following:

import UIKit
import SpriteKit
class GameViewController: UIViewController {
  override func viewDidLoad() {
    let scene = GameScene(size: view.bounds.size)
    let skView = view as! SKView
    skView.showsFPS = true
    skView.showsNodeCount = true
    skView.ignoresSiblingOrder = true
    scene.scaleMode = .resizeFill
  override var prefersStatusBarHidden: Bool {
    return true

GameViewController is a normal UIViewController, except that its root view is a SKView, which is a view that contains a SpriteKit scene.

Here, you’ve implemented viewDidLoad() to create a new instance of the GameScene on startup, with the same size of the view itself.

That’s it for the initial setup – now let’s get something on the screen!

Adding a Sprite

First, download the resources for this project.

Open Assets.xcassets and drag in the images from the sprites.atlas folder from the resources:


Then drag the Sounds folder from the resources into your project navigator. Make sure that Copy items into destination group’s folder (if needed) and Create Groups are checked, and that your SpriteKitSimpleGame target is selected.


Next, open GameScene.swift and replace the contents with the following:

import SpriteKit

class GameScene: SKScene {
  // 1
  let player = SKSpriteNode(imageNamed: "player")

  override func didMove(to view: SKView) {
    // 2
    backgroundColor = SKColor.white
    // 3
    player.position = CGPoint(x: size.width * 0.1, y: size.height * 0.5)
    // 4

Let’s go over this step-by-step.

  1. Here you declare a private constant for the player (i.e. the ninja), which is an example of a sprite. As you can see, creating a sprite is easy – simply pass in the name of the image to use.
  2. Setting the background color of a scene in SpriteKit is as simple as setting the backgroundColor property. Here you set it to white.
  3. You position the sprite to be 10% across vertically, and centered horizontally.
  4. To make the sprite appear on the scene, you must add it as a child of the scene. This is similar to how you make views children of other views.

Build and run, and voila – ladies and gentlemen, the ninja has entered the building!


Moving Monsters

Next you want to add some monsters into your scene for your ninja to combat. To make things more interesting, you want the monsters to be moving – otherwise there wouldn’t be much of a challenge! So let’s create the monsters slightly off screen to the right, and set up an action for them telling them to move to the left.

Add the following methods to GameScene.swift (inside the class, before the closing curly brace):

func random() -> CGFloat {
  return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
func random(min: CGFloat, max: CGFloat) -> CGFloat {
  return random() * (max - min) + min
func addMonster() {
  // Create sprite
  let monster = SKSpriteNode(imageNamed: "monster")
  // Determine where to spawn the monster along the Y axis
  let actualY = random(min: monster.size.height/2, max: size.height - monster.size.height/2)
  // Position the monster slightly off-screen along the right edge,
  // and along a random position along the Y axis as calculated above
  monster.position = CGPoint(x: size.width + monster.size.width/2, y: actualY)
  // Add the monster to the scene
  // Determine speed of the monster
  let actualDuration = random(min: CGFloat(2.0), max: CGFloat(4.0))
  // Create the actions
  let actionMove = SKAction.move(to: CGPoint(x: -monster.size.width/2, y: actualY), duration: TimeInterval(actualDuration))
  let actionMoveDone = SKAction.removeFromParent()
  monster.run(SKAction.sequence([actionMove, actionMoveDone]))

I’ve spelled out things in a verbose manner here to make things as easy to understand as possible. The first part should make sense based on what we’ve discussed so far: you do some simple calculations to determine where you want to create the object, set the position of the object, and add it to the scene the same way you did for the player sprite.

The new element here is adding actions. SpriteKit provides a lot of extremely handy built-in actions that help you easily change the state of sprites over time, such as move actions, rotate actions, fade actions, animation actions, and more. Here you use three actions on the monster:

  • SKAction.move(to::duration:): You use this action to direct the object to move off-screen to the left. Note that you can specify the duration for how long the movement should take, and here you vary the speed randomly from 2-4 seconds.
  • SKAction.removeFromParent(): SpriteKit comes with a handy action that removes a node from its parent, effectively “deleting it” from the scene. Here you use this action to remove the monster from the scene when it is no longer visible. This is important because otherwise you’d have an endless supply of monsters and would eventually consume all device resources.
  • SKAction.sequence(_:): The sequence action allows you to chain together a sequence of actions that are performed in order, one at a time. This way, you can have the “move to” action perform first, and once it is complete perform the “remove from parent” action.
Note: This code block includes some helper methods to generate a random number within a range using arc4random(). This suffices for our simple random number generation needs in this game, but if you want more advanced functionality, check out the random number APIs in iOS 9’s new GameplayKit.

One last thing before you go. You need to actually call the method to create monsters! And to make things fun, let’s have monsters continuously spawning over time.

Simply add the following code to the end of didMove(to:):

    SKAction.wait(forDuration: 1.0)

Here you run a sequence of actions to call a block of code (you can seamlessly pass in your addMonster() method here thanks to the power of Swift), and then wait for 1 second. You then repeat this sequence of actions endlessly.

That’s it! Build and run the project, now you should see monsters happily moving across the screen:


Shooting Projectiles

At this point, the ninja is just begging for some action – so let’s add shooting! There are many ways you could implement shooting, but for this game you are going to make it so when the user taps the screen, it shoots a projectile from the player in the direction of the tap.

I want to use a “move to” action to implement this to keep things at a beginner level, but in order to use this you have to do a little math.

This is because the “move to” action requires you to give a destination for the projectile, but you can’t just use the touch point because the touch point represents just the direction to shoot relative to the player. You actually want to keep the bullet moving through the touch point until the bullet goes off-screen.

Here’s a picture that illustrates the matter:

Projectile Triangle

So as you can see, you have a small triangle created by the x and y offset from the origin point to the touch point. You just need to make a big triangle with the same ratio – and you know you want one of the endpoints to be off the screen.

To run these calculations, it really helps if you have some basic vector math routines you can call (like methods to add and subtract vectors). However, SpriteKit doesn’t have any by default so you’ll have to write your own.

Luckily they are very easy to write thanks to the power of Swift operator overloading. Add these functions to the top of your file, right before the GameScene class:

func + (left: CGPoint, right: CGPoint) -> CGPoint {
  return CGPoint(x: left.x + right.x, y: left.y + right.y)

func - (left: CGPoint, right: CGPoint) -> CGPoint {
  return CGPoint(x: left.x - right.x, y: left.y - right.y)

func * (point: CGPoint, scalar: CGFloat) -> CGPoint {
  return CGPoint(x: point.x * scalar, y: point.y * scalar)

func / (point: CGPoint, scalar: CGFloat) -> CGPoint {
  return CGPoint(x: point.x / scalar, y: point.y / scalar)

#if !(arch(x86_64) || arch(arm64))
func sqrt(a: CGFloat) -> CGFloat {
  return CGFloat(sqrtf(Float(a)))

extension CGPoint {
  func length() -> CGFloat {
    return sqrt(x*x + y*y)
  func normalized() -> CGPoint {
    return self / length()

These are standard implementations of some vector math functions. If you’re confused about what’s going on here or are new to vector math, check out this quick vector math explanation.

Next, add a new method to the file (again, before the closing curly brace):

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

  // 1 - Choose one of the touches to work with
  guard let touch = touches.first else {
  let touchLocation = touch.location(in: self)
  // 2 - Set up initial location of projectile
  let projectile = SKSpriteNode(imageNamed: "projectile")
  projectile.position = player.position
  // 3 - Determine offset of location to projectile
  let offset = touchLocation - projectile.position
  // 4 - Bail out if you are shooting down or backwards
  if (offset.x < 0) { return }
  // 5 - OK to add now - you've double checked position
  // 6 - Get the direction of where to shoot
  let direction = offset.normalized()
  // 7 - Make it shoot far enough to be guaranteed off screen
  let shootAmount = direction * 1000
  // 8 - Add the shoot amount to the current position
  let realDest = shootAmount + projectile.position
  // 9 - Create the actions
  let actionMove = SKAction.move(to: realDest, duration: 2.0)
  let actionMoveDone = SKAction.removeFromParent()
  projectile.run(SKAction.sequence([actionMove, actionMoveDone]))

There's a lot going on here, so let's review it step by step.

  1. One of the cool things about SpriteKit is that it includes a category on UITouch with location(in:) and previousLocation(in:) methods. These let you find the coordinate of a touch within a SKNode's coordinate system. In this case, you use it to find out where the touch is within the scene's coordinate system.
  2. You then create a projectile and place it where the player is to start. Note you don't add it to the scene yet, because you have to do some sanity checking first - this game does not allow the ninja to shoot backwards.
  3. You then subtract the projectile's current position from the touch location to get a vector from the current position to the touch location.
  4. If the X value is less than 0, this means the player is trying to shoot backwards. This is is not allowed in this game (real ninjas don't look back!), so just return.
  5. Otherwise, it's OK to add the projectile to the scene.
  6. Convert the offset into a unit vector (of length 1) by calling normalized(). This will make it easy to make a vector with a fixed length in the same direction, because 1 * length = length.
  7. Multiply the unit vector in the direction you want to shoot in by 1000. Why 1000? It will definitely be long enough to go past the edge of the screen :]
  8. Add the shoot amount to the current position to get where it should end up on the screen.
  9. Finally, create move(to:, duration:) and removeFromParent() actions like you did earlier for the monster.

Build and run, and now your ninja should be able to fire away at the oncoming hordes!


Collision Detection and Physics: Overview

So now you have shurikens flying everywhere – but what your ninja really wants to do is to lay some smack down. So let’s add in some code to detect when your projectiles intersect your targets.

One of the nice things about SpriteKit is it comes with a physics engine built right in! Not only are physics engines great for simulating realistic movement, but they are also great for collision detection purposes.

Let's set up the game to use SpriteKit's physics engine to determine when monsters and projectiles collide. At a high level, here's what you're going to do:

  • Set up the physics world. A physics world is the simulation space for running physics calculations. One is set up on the scene by default, and you might want to configure a few properties on it, like gravity.
  • Create physics bodies for each sprite. In SpriteKit, you can associate a shape to each sprite for collision detection purposes, and set certain properties on it. This is called a physics body. Note that the physics body does not have to be the exact same shape as the sprite. Usually it's a simpler, approximate shape rather than pixel-perfect, since that is good enough for most games and performant.
  • Set a category for each type of sprite. One of the properties you can set on a physics body is a category, which is a bitmask indicating the group (or groups) it belongs to. In this game, you're going to have two categories - one for projectiles, and one for monsters. Then later when two physics bodies collide, you can easily tell what kind of sprite you're dealing with by looking at its category.
  • Set a contact delegate. Remember that physics world from earlier? Well, you can set a contact delegate on it to be notified when two physics bodies collide. There you'll write some code to examine the categories of the objects, and if they're the monster and projectile, you'll make them go boom!

Now that you understand the battle plan, it's time to put it into action!

Collision Detection and Physics: Implementation

Start by adding this struct to the top of GameScene.swift:

struct PhysicsCategory {
  static let None      : UInt32 = 0
  static let All       : UInt32 = UInt32.max
  static let Monster   : UInt32 = 0b1       // 1
  static let Projectile: UInt32 = 0b10      // 2

This is setting up the constants for the physics categories you'll need in a bit - no pun intended! :]

Note: You may be wondering what the fancy syntax is here. Note that the category on SpriteKit is just a single 32-bit integer, and acts as a bitmask. This is a fancy way of saying each of the 32-bits in the integer represents a single category (and hence you can have 32 categories max). Here you're setting the first bit to indicate a monster, the next bit over to represent a projectile, and so on.

Next, mark GameScene as implementing the SKPhysicsContactDelegate protocol:

class GameScene: SKScene, SKPhysicsContactDelegate {

Then inside didMoveToView(_:) add these lines after adding the player to the scene:

physicsWorld.gravity = CGVector.zero
physicsWorld.contactDelegate = self

This sets up the physics world to have no gravity, and sets the scene as the delegate to be notified when two physics bodies collide.

Inside the addMonster() method, add these lines right after creating the monster sprite:

monster.physicsBody = SKPhysicsBody(rectangleOf: monster.size) // 1
monster.physicsBody?.isDynamic = true // 2
monster.physicsBody?.categoryBitMask = PhysicsCategory.Monster // 3
monster.physicsBody?.contactTestBitMask = PhysicsCategory.Projectile // 4
monster.physicsBody?.collisionBitMask = PhysicsCategory.None // 5

Let's go over what this does line by line.

  1. Creates a physics body for the sprite. In this case, the body is defined as a rectangle of the same size of the sprite, because that's a decent approximation for the monster.
  2. Sets the sprite to be dynamic. This means that the physics engine will not control the movement of the monster - you will through the code you've already written (using move actions).
  3. Sets the category bit mask to be the monsterCategory you defined earlier.
  4. The contactTestBitMask indicates what categories of objects this object should notify the contact listener when they intersect. You choose projectiles here.
  5. The collisionBitMask indicates what categories of objects this object that the physics engine handle contact responses to (i.e. bounce off of). You don't want the monster and projectile to bounce off each other - it's OK for them to go right through each other in this game - so you set this to 0.

Next add some similar code to touchesEnded(_:withEvent:), right after the line setting the projectile's position:

projectile.physicsBody = SKPhysicsBody(circleOfRadius: projectile.size.width/2)
projectile.physicsBody?.isDynamic = true
projectile.physicsBody?.categoryBitMask = PhysicsCategory.Projectile
projectile.physicsBody?.contactTestBitMask = PhysicsCategory.Monster
projectile.physicsBody?.collisionBitMask = PhysicsCategory.None
projectile.physicsBody?.usesPreciseCollisionDetection = true

As a test, see if you can understand each line here and what it does. If not, just refer back to the points explained above!

As a second test, see if you can spot two differences. Answer below!

Solution Inside: What Are the Differences? SelectShow

Next, add a method that will be called when the projectile collides with the monster (before the closing curly brace). Note that nothing calls this automatically, you will be calling this later.

func projectileDidCollideWithMonster(projectile: SKSpriteNode, monster: SKSpriteNode) {

All you do here is remove the projectile and monster from the scene when they collide. Pretty simple, eh?

Now it's time to implement the contact delegate method. Add the following new method to the file (again, before the closing curly brace):

func didBegin(_ contact: SKPhysicsContact) {

  // 1
  var firstBody: SKPhysicsBody
  var secondBody: SKPhysicsBody
  if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
    firstBody = contact.bodyA
    secondBody = contact.bodyB
  } else {
    firstBody = contact.bodyB
    secondBody = contact.bodyA
  // 2
  if ((firstBody.categoryBitMask & PhysicsCategory.Monster != 0) &&
      (secondBody.categoryBitMask & PhysicsCategory.Projectile != 0)) {
    if let monster = firstBody.node as? SKSpriteNode, let
      projectile = secondBody.node as? SKSpriteNode {
      projectileDidCollideWithMonster(projectile: projectile, monster: monster)

Since you set the scene as the contactDelegate of the physics world earlier, this method will be called whenever two physics bodies collide (and their contactTestBitMasks are set appropriately).

There are two parts to this method:

  1. This method passes you the two bodies that collide, but does not guarantee that they are passed in any particular order. So this bit of code just arranges them so they are sorted by their category bit masks so you can make some assumptions later.
  2. Finally, it checks to see if the two bodies that collide are the projectile and monster, and if so calls the method you wrote earlier.

Give it a build and run, and now when your projectiles intersect targets they should disappear!

Finishing Touches

You’re pretty close to having a workable (but extremely simple) game now. You just need to add some sound effects and music (since what kind of game doesn’t have sound!) and some simple game logic.

You already have some cool background music I made and an awesome pew-pew sound effect in your project, from the resources for this tutorial you added to your project earlier. You just need to play them!

To do this, add these line to the end of didMove(to:):

let backgroundMusic = SKAudioNode(fileNamed: "background-music-aac.caf")
backgroundMusic.autoplayLooped = true

This uses SKAudioNode, a new class introduced in iOS 9, to play and loop the background music for your game.

As for the sound effect, add this line to the top of touchesEnded(_:withEvent:):

run(SKAction.playSoundFileNamed("pew-pew-lei.caf", waitForCompletion: false))

Pretty handy, eh? You can play a sound effect with one line!

Build and run, and enjoy your groovy tunes!

Note: If you don't hear the background music, try running on a device instead of the simulator.

Game Over, Man!

Now, let’s create a new scene that will serve as your “You Win” or “You Lose” indicator. Create a new file with the iOS\Source\Swift File template, name the file GameOverScene and click Create.

Then replace GameOverScene.swift with the following:

import Foundation
import SpriteKit
class GameOverScene: SKScene {
  init(size: CGSize, won:Bool) {
    super.init(size: size)
    // 1
    backgroundColor = SKColor.white
    // 2
    let message = won ? "You Won!" : "You Lose :["
    // 3
    let label = SKLabelNode(fontNamed: "Chalkduster")
    label.text = message
    label.fontSize = 40
    label.fontColor = SKColor.black
    label.position = CGPoint(x: size.width/2, y: size.height/2)
    // 4
      SKAction.wait(forDuration: 3.0),
      SKAction.run() {
        // 5
        let reveal = SKTransition.flipHorizontal(withDuration: 0.5)
        let scene = GameScene(size: size)
        self.view?.presentScene(scene, transition:reveal)
  // 6
  required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")

There are five parts to point out here

  1. Sets the background color to white, same as you did for the main scene.
  2. Based on the won parameter, sets the message to either "You Won" or "You Lose".
  3. This is how you display a label of text to the screen with SpriteKit. As you can see, it's pretty easy - you just choose your font and set a few parameters.
  4. Finally, this sets up and runs a sequence of two actions. I've included them all inline here to show you how handy that is (instead of having to make separate variables for each action). First it waits for 3 seconds, then it uses the runBlock action to run some arbitrary code.
  5. This is how you transition to a new scene in SpriteKit. First you can pick from a variety of different animated transitions for how you want the scenes to display - you choose a flip transition here that takes 0.5 seconds. Then you create the scene you want to display, and use the presentScene(_:transition:) method on the self.view property.
  6. If you override an initializer on a scene, you must implement the required init(coder:) initializer as well. However this initializer will never be called, so you just add a dummy implementation with a fatalError(_:) for now.

So far so good, now you just need to set up your main scene to load the game over scene when appropriate.

Switch back to GameScene.swift, and inside addMonster(), replace the last line that runs the actions on the monster with the following:

let loseAction = SKAction.run() {
  let reveal = SKTransition.flipHorizontal(withDuration: 0.5)
  let gameOverScene = GameOverScene(size: self.size, won: false)
  self.view?.presentScene(gameOverScene, transition: reveal)
monster.run(SKAction.sequence([actionMove, loseAction, actionMoveDone]))

This creates a new "lose action" that displays the game over scene when a monster goes off-screen. See if you understand each line here, if not refer to the explanation for the previous code block.

Also, another pop-quiz for you: why do you run the loseAction before actionMoveDone? Try reversing them to see what happens if you don't know.

Solution Inside: Why is Lose Action First? SelectShow

Now you should handle the win case too - don't be cruel to your players! :] Add a new property to the top of GameScene, right after the declaration of player:

var monstersDestroyed = 0

And add this to the bottom of projectile(_:didCollideWithMonster:):

monstersDestroyed += 1
if (monstersDestroyed > 30) {
  let reveal = SKTransition.flipHorizontal(withDuration: 0.5)
  let gameOverScene = GameOverScene(size: self.size, won: true)
  self.view?.presentScene(gameOverScene, transition: reveal)

Go ahead and give it a build and run, and you should now have win and lose conditions and see a game over scene when appropriate!


Where To Go From Here?

And that's a wrap! Here is the full source code for this SpriteKit Swift Tutorial for beginners.

I hope you enjoyed learning about SpriteKit and are inspired to make your own game. If you have any questions or comments about this tutorial, please join the discussion below!

If you want to learn more about SpriteKit, you should check out our book 2D Apple Games by Tutorials:

In this book we'll teach you everything you need to know to make great games for iOS, tvOS, watchOS and macOS - from physics, to tile maps, to particle systems, and even how to make your games "juicy" with polish and special effects!

Ray Wenderlich

Ray is part of a great team - the raywenderlich.com team, a group of over 100 developers and editors from across the world. He and the rest of the team are passionate both about making apps and teaching others the techniques to make them.

When Ray’s not programming, he’s probably playing video games, role playing games, or board games.

Other Items of Interest

Save time.
Learn more with our video courses.

raywenderlich.com Weekly

Sign up to receive the latest tutorials from raywenderlich.com each week, and receive a free epic-length tutorial as a bonus!

Advertise with Us!

PragmaConf 2016 Come check out Alt U

Our Books

Our Team

Video Team

... 27 total!

iOS Team

... 73 total!

Android Team

... 33 total!

Unity Team

... 15 total!

Articles Team

... 12 total!

Resident Authors Team

... 29 total!

Podcast Team

... 7 total!

Recruitment Team

... 9 total!