Create a game like Flappy Bird for iOS using SpriteKit

Flappy Bird is one of the most infamous games ever to hit the App Store. What was it’s key to success? It was a simple game that offered players a unique challenge.

This tutorial will show you how to create a game similar to Flappy Bird for iOS using only SpriteKit.

Create a new SpriteKit Game:

  • Open XCode and click File > New > Project
  • Below the iOS category, select Application and Game
  • Click Next
  • Beside Product Name, enter HappyBird
  • For the Language, select Swift
  • For the Game Technology, select SpriteKit
  • For Devices, select iPhone and click Next
  • Select a location to save the project and click Create

Configure the Environment:

Note: Download the asset/image files here

  • Highlight the HappyBird project
  • Uncheck Landscape Left and Landscape Right
  • Drag and Drop background.png, topPipe.png, bottomPipe,png and floor.png into the project
  • Ensure that Copy Items if Needed is selected
  • In Finder, create a new folder called atlas
  • Copy player1.png, player2.png, player3.png and player4.png into the player.altas folder
  • Drag and Drop the atlas folder into the project. All of these files should now appear below the yellow HappyBird folder icon within XCode
  • Open swift
  • Below the viewDidLoad() function, change the sibling order attribute from true to false:

    Changing this setting allows our game to place our objects in the order we want, instead of letting the computer randomly decide.


  • Open GameScene.swift
  • Remove all of the code within the didMoveToView and touchesBegan function


Add the SKPhysicsContactDelegate to the GameScene Class:

The scene is all set up, so now we’re ready to building our game!

Add the background to the Scene:

  • Open GameScene.swift
  • Within GameScene class, define a variable for the background node:

  • Within the didMoveToView function, enter the following code:

  • The preceding code assigns and image (background) to the scene. Note that you do not need to include the “.png” extension as SpriteKit will automatically pick up on it.
  • The .anchorPoint and .position routines define where the background will be placed on the screen
  • The backgroundColor property allows you to define the background color. In this case it will be the same color as our background, allowing it to seamlessly blend.
  • Finally, add the background to the screen by entering the following code in the didMoveToView section:addChild(self.myBackground)
  • Run the project. You will see a simple screen with a background image of trees


Add the floor to the Scene:

  • Within GameScene class, define a variable for two floor nodes:

  • Within the didMoveToView function, enter the following code:

  • As you seen with the background image, this adds the floor images to the nodes and sets up the anchor points and positions. The position of “myFloor2” is the same distance as the length of the “myFloor1”. This allows the image to continuously repeat itself.
  • Finally, add the floor nodes to the Scene:

  • Our project is coming together nicely! If you run the project you will now see a floor. Next, we’ll add the player sprite to the scene

Add the player (bird) to the scene:

  • Within the GameScene class, enter the following code:

  • The first line creates a texture atlas. A texture atlas is a series of images that make an animation. The second line creates an array of textures to pick from.
  • Within the didMoveToView function, define the array of images:

  • Now, set up the bird’s initial position:

  • Define the bird’s animation, and repeat the animation forever:

  • Lastly, add the bird to the scene:

Now, if all went well, we can see the bird flapping his wings in the Scene:

Bird alone

Add some pipes to the scene:

We’re going to add 4 pipes to our Scene.

  • Within the GameScene class, enter the following code:

  • The second-last variable will be used to determine if our game has started.
  • The last variable will be used to set a random size for our pipe.
  • Set up the location and images of the pipes within the didMoveToView function:

  • Lastly, add the pipes to the scene:

We’ve now added pipes to the scene, however we won’t see them even though we’ve added the children nodes. This is because we haven’t started moving the pipes and they are theoretically on their way from the right-hand side of the screen.

Scroll the Scene

  • Let’s scroll the scene now. In the update function, add the following code:

  • This will push the floor left continuously and re-draw the same floor on the right side to give the appearance of a seamless moving floor.
  • Now, to animate the pipes, enter the following code:

  • Create a new function, a random number generator, to make the pipes random sizes:

Now, in the touchesBegan function, tell the computer that the game has started. This will occur when you touch (or click) the screen.

We now have a bird flying across the screen between pipes. It looks great, but now we need to add some challenge to the game. We’ll do this by applying physics to our nodes.


Apply Physics to the Scene:

  • In the GameScene class, we’re going to start by adding a category for our bitmask. This will allow us to differentiate between pipes and other objects in the scene:

  • In the didMoveToView class, create a physics body around the entire screen using the edgeLoopFromRect Also, create a contactDelegate for the world:

  • Now, add some bitmask objects to each pipe:

Screen Shot 2015-12-30 at 9.47.35 AM

  • Now, create a physics body for the pipes and floor:

  • Prevent the pipes from moving around on the screen by setting the physics dynamics to false:

  • Create a function to set up the bird’s physics by making a circular border around him:

  • In the touchesBesgan() function, the following code will determine if the bird is active, and apply a force to give the appearance of jumping/flying:

You can now run the game and see that the bird will hit the pipes and the floor. He might even fly off of the screen! Next, we’ll add some finishing touches to the game to make it more playable.

Finishing Touches:

  • In the update() function, we’ll add the following code to prevent the bird from moving off of the screen too far. Also, we’ll prevent him from rotating (unless this is a desired visual effect):

  • Finally, we’ll add the following function to detect when the bird hits a pipe. At this point, you’ll see a message in XCode saying that the pipe was hit. Here, you could program a game over sequence, or a point system that will add a point every time a pipe is hit:

That’s it that’s all! If I missed anything or if the code can be improved, or heck if you just have a question feel free to post it in the comments.

Download the complete project here


    1. The randomBetweenNumbers is a custom function – just make sure you are adding the code below somewhere outside of all of your other functions:

      func randomBetweenNumbers(firstNum: CGFloat, secondNum: CGFloat) -> CGFloat{

      return CGFloat(arc4random()) / CGFloat(UINT32_MAX) * abs(firstNum – secondNum) + min(firstNum, secondNum)


  1. myBackground.position = CGPointMake(100, 0);

    I don’t understand how this works. AnchorPoint is @ (0,0) that means, this could should make the background start at 100th pixel in X direction right? how does it start at the 0th pixel itself?

    I did enable the landscape mode just to have a check, and in landscape mode it starts from 100th pixel. I just could not understand how it works

  2. Thanks, fantastic tutorial. The only thing I would change is to make all the offsets like pipe height and x position etc. relative to the size of the scene.

    What took me the longest to figure out is:
    – Scene size – I never worked with SK before so I was surprised to find that the scene has a fixed size, and the coordinate system is based on that, and later scaled to the screen.
    – Positioning of sprites. The sprite coordinate system with the lower left corner at 0,0 took some getting used to vs. the normal view layout with 0,0 in the upper left.

    Both these things worked together to make me scratch my head quite a bit – like why do these sprites appear where they appear, and why are they that size.

Comments are closed.