How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

26
digitalbreed matthias gall – product architect Home Portfolio Blog Book Reviews Imprint / Contact How to build a game like Flappy Bird with Xcode and SpriteKit By matt On 2/10/2014 In Game Development, Software Engineering With 22 Comments Permalink This is a developing blog post. Keep coming back to see it progressing. This is a developing blog post. Keep coming back to see it progressing. When I heard about Flappy Bird for the first time, the hype was already in its final phase: developer Dong Nguyen had decided to pull the app from the stores in “ 22 hours from now“. Apart from overreacting users and an allegedly daily advertising revenue of up to 50,000 US$, the simple game mechanics were something that caught my attention. The concept of clicking/tapping to keep the player on track wasn’t really an innovation in itself, but given the hype it caused, it was certainly worth a closer look. As a Sunday evening challenge, I tried to reproduce the game mechanics and ended up with less than 200 lines of code. Graphic assets Since the app was already removed from the stores when I started working on the clone, I had to rely on screenshots and videos of the original game to reproduce the individual sprites. I used The Gimp to produce the bird (two simple frames for animation), the pipes (upper and lower version), the distant background and the ground. How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy... 1 de 26 18/02/14 19:32

Transcript of How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

Page 1: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

digitalbreed

matthias gall – product architect

HomePortfolioBlogBook ReviewsImprint / Contact

How to build a game like Flappy Bird with Xcode and SpriteKit

By matt On 2/10/2014 In Game Development, Software Engineering With 22 Comments Permalink

This is a developing blog post. Keep coming back to see it progressing.This is a developing blog post. Keep coming back to see it progressing.

When I heard about Flappy Bird for the first time, the hype was already in its final phase: developerDong Nguyen had decided to pull the app from the stores in “22 hours from now“. Apart fromoverreacting users and an allegedly daily advertising revenue of up to 50,000 US$, the simple gamemechanics were something that caught my attention. The concept of clicking/tapping to keep the playeron track wasn’t really an innovation in itself, but given the hype it caused, it was certainly worth a closerlook. As a Sunday evening challenge, I tried to reproduce the game mechanics and ended up with lessthan 200 lines of code.

Graphic assets

Since the app was already removed from the stores when I started working on the clone, I had to rely onscreenshots and videos of the original game to reproduce the individual sprites. I used The Gimp toproduce the bird (two simple frames for animation), the pipes (upper and lower version), the distantbackground and the ground.

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

1 de 26 18/02/14 19:32

Page 2: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

Note that the created files are a little too small for an iPhone display. Therefore, in the course of thistutorial, you’ll see that I simply doubled the size by scaling every sprite by a factor of 2. In order tomaintain the 8 bit retro look I changed the filtering mode of the textures fromSKTextureFilteringLinear (standard) to SKTextureFilteringNearest.

You can download the created files with the final project.

Xcode project setup

iOS 7 comes with a great new framework called Sprite Kit. It hides lots of the iOS UI developmentdetails game programmers are not necessarily familiar with (outlets anyone?) and builds upon a basicgame infrastructure they are are more used to (e.g. rendering loop and scene graph). For all iOSdevelopers, focussing on the game mechanics becomes a breeze.

When Xcode starts, simply select “Create a new Xcode project” from the splash screen.

From the available project templates, select “SpriteKit Game”.

Now enter some project details. You can change them later if you need to.

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

2 de 26 18/02/14 19:32

Page 3: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

Select a place to store the project files. I usually create a new subfolder in my Documents folder.

Finally, the project is created and we’re ready for development.

The bird

The template project comes with some sample code and assets that need to be removed. Delete theSpaceship.png graphic from the project and add the Bird1.png and Bird2.png files instead. Alsoremove the existing code in the initWithSize and touchesBegan methods of MyScene.m.

In initWithSize, create the bird sprite and add it to the scene. To access the bird easily from other classmethods, we declare it as an ivar.

123456789

10111213141516171819202122232425262728293031

#import "MyScene.h" @interface MyScene () { SKSpriteNode* _bird;}@end @implementation MyScene -(id)initWithSize:(CGSize)size { if (self = [super initWithSize:size]) { /* Setup your scene here */ SKTexture* birdTexture1 = [SKTexture textureWithImageNamed:@ birdTexture1.filteringMode = SKTextureFilteringNearest; _bird = [SKSpriteNode spriteNodeWithTexture:birdTexture1]; [_bird setScale:2.0]; _bird.position = CGPointMake(self.frame.size.width / 4, CGRectGetMidY(sel [self addChild:_bird]; } return self;} -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { /* Called when a touch begins */} -(void)update:(CFTimeInterval)currentTime { /* Called before each frame is rendered */

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

3 de 26 18/02/14 19:32

Page 4: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

One important thing to remember is that the SpriteKit’s scene coordinate system has it’s origin at thebottom left point and the positive y- and x-axes extend to the top and right of the screen. A sprite’sdefault anchor point is always the center. Using the code above, the bird is placed on the vertical centerand end of the horizontal first quarter of the screen.

Hooray, we’re nearly there! It won’t get much harder than that, believe me.

Animating the bird

Animating is pretty easy thanks to SpriteKit Actions. We simply create a sequence of texture-changesand loop them endlessly with a little delay in order to produce the illusion of flapping wings. I believethat the original game used some more frames, but we’ll go with two for the sake of simplicity.

We’ll have to load the second bird sprite, too, produce an SKAction to animate them, and attach thisanimation to the bird.

This results in a simple animation like this:

323334

} @end

123456789

1011

SKTexture* birdTexture1 = [SKTexture textureWithImageNamed:@"Bird1"birdTexture1.filteringMode = SKTextureFilteringNearest;SKTexture* birdTexture2 = [SKTexture textureWithImageNamed:@"Bird2"birdTexture2.filteringMode = SKTextureFilteringNearest; SKAction* flap = [SKAction repeatActionForever:[SKAction animateWithTextures:@[bi _bird = [SKSpriteNode spriteNodeWithTexture:birdTexture1];[_bird setScale:2.0];_bird.position = CGPointMake(self.frame.size.width / 4, CGRectGetMidY(self.frame)[_bird runAction:flap];

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

4 de 26 18/02/14 19:32

Page 5: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

Adding ground and background

Most of the screen background is a bright blue sky. Let’s fill the screen accordingly. We store the skycolor in an ivar for later…

The background and ground sprites are repeating patterns. After adding Skyline.png and Ground.png tothe project, we setup the textures first and then fill the full screen width with the sprites.

This leads to the following static scene.

123456789

1011121314

@interface MyScene () { SKSpriteNode* _bird; SKColor* _skyColor;}@end @implementation MyScene -(id)initWithSize:(CGSize)size { if (self = [super initWithSize:size]) { /* Setup your scene here */ _skyColor = [SKColor colorWithRed:113.0/255.0 green:197.0/255.0 blue:207. [self setBackgroundColor:_skyColor];

123456789

101112131415161718192021222324

// Create ground SKTexture* groundTexture = [SKTexture textureWithImageNamed:@"Ground"groundTexture.filteringMode = SKTextureFilteringNearest; for( int i = 0; i < 2 + self.frame.size.width / ( groundTexture.size.width * 2 ); SKSpriteNode* sprite = [SKSpriteNode spriteNodeWithTexture:groundTexture]; [sprite setScale:2.0]; sprite.position = CGPointMake(i * sprite.size.width, sprite.size.height / 2); [self addChild:sprite];} // Create skyline SKTexture* skylineTexture = [SKTexture textureWithImageNamed:@"Skyline"skylineTexture.filteringMode = SKTextureFilteringNearest; for( int i = 0; i < 2 + self.frame.size.width / ( skylineTexture.size.width * 2 ) SKSpriteNode* sprite = [SKSpriteNode spriteNodeWithTexture:skylineTexture]; [sprite setScale:2.0]; sprite.zPosition = -20; sprite.position = CGPointMake(i * sprite.size.width, sprite.size.height / 2 + [self addChild:sprite];}

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

5 de 26 18/02/14 19:32

Page 6: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

You may have noticed that I created one more tile than necessary. This is required for the animation: Wecan create the illusion of movement by simply moving each sprite to the left for a full width and thenresetting it to the original position. When the tiles wander to the left, a gap opens at the right edge of thescreen. We use the extra tile to fill that gap.

123456789

101112131415161718192021222324252627282930313233

// Create ground SKTexture* groundTexture = [SKTexture textureWithImageNamed:@"Ground"groundTexture.filteringMode = SKTextureFilteringNearest; SKAction* moveGroundSprite = [SKAction moveByX:-groundTexture.size.width*2 y:0 duSKAction* resetGroundSprite = [SKAction moveByX:groundTexture.size.width*2 y:0 duSKAction* moveGroundSpritesForever = [SKAction repeatActionForever:[SKAction sequ for( int i = 0; i < 2 + self.frame.size.width / ( groundTexture.size.width * 2 ); // Create the sprite SKSpriteNode* sprite = [SKSpriteNode spriteNodeWithTexture:groundTexture]; [sprite setScale:2.0]; sprite.position = CGPointMake(i * sprite.size.width, sprite.size.height / 2); [sprite runAction:moveGroundSpritesForever]; [self addChild:sprite];} // Create skyline SKTexture* skylineTexture = [SKTexture textureWithImageNamed:@"Skyline"skylineTexture.filteringMode = SKTextureFilteringNearest; SKAction* moveSkylineSprite = [SKAction moveByX:-skylineTexture.size.width*2 y:0 SKAction* resetSkylineSprite = [SKAction moveByX:skylineTexture.size.width*2 y:0 SKAction* moveSkylineSpritesForever = [SKAction repeatActionForever:[SKAction seq for( int i = 0; i < 2 + self.frame.size.width / ( skylineTexture.size.width * 2 ) SKSpriteNode* sprite = [SKSpriteNode spriteNodeWithTexture:skylineTexture]; [sprite setScale:2.0]; sprite.zPosition = -20; sprite.position = CGPointMake(i * sprite.size.width, sprite.size.height / 2 + [sprite runAction:moveSkylineSpritesForever];

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

6 de 26 18/02/14 19:32

Page 7: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

Two layers of the scene are scrolling with different pace (speed scale factors 0.1 and 0.02 above), leadingto an illusion of depth. This effect has been used in 2D video games for ages and is called parallaxscrolling.

Let’s add some physics

Until now, everything in the scene is just fake. The bird doesn’t even move. But we can easily enable theSpriteKit physics engine in order to add some realistic movement to the scene.

SpriteKit allows to attach a physics body to every scene node. The physics body has certain propertieslike mass, density, friction,… and it can interact with other physics-enabled entities in the scene. Once aphysics body is created, the owner node is controlled by physics.

Let’s start with the bird. We will represent it’s physical shape by a circle.

When we start our clone now, we’ll see the bird falling straight down – and out of the screen. In order toavoid that, we will have to create a physics body for the ground as well. We could attach it to each of theground tiles, but remember that they’re continuously moving left and then resetting their position. Thiscould lead to some strange effects once the bird collides with such a ground tile. So instead, we cansimply create an empty node with a rectangular physics body which spans the full ground.

Add this below the creation of the ground sprites:

3435

[self addChild:sprite];}

123456789

10

_bird = [SKSpriteNode spriteNodeWithTexture:birdTexture1];[_bird setScale:2.0];_bird.position = CGPointMake(self.frame.size.width / 4, CGRectGetMidY(self.frame)[_bird runAction:flap]; _bird.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:_bird.size.height / 2];_bird.physicsBody.dynamic = YES;_bird.physicsBody.allowsRotation = NO; [self addChild:_bird];

123456

// Create ground physics container SKNode* dummy = [SKNode node];dummy.position = CGPointMake(0, groundTexture.size.height);dummy.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(self.frame.sdummy.physicsBody.dynamic = NO;

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

7 de 26 18/02/14 19:32

Page 8: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

Note that the bird has property dynamic set to YES, while the ground (and all other “static” entities) havedynamic set to NO. This is because that only the bird is affected by interactions with the physic world.The remaining entities are under our control and won’t change their position or rotation e.g. due to acollision.

With these changes in place, you’ll see our little bird falling to the ground.

The bird is falling a little too fast for my taste. We have multiple options to control this behavior, let’s trythe easiest and most obvious one first: we’ll change the world’s gravity!

At the beginning of the scene setup, simply add:

This will reduce the gravity from an authentic -9.8m/s^2 to only -5m/s^2, making the bird falling slower.

In order to let the bird raise on a click/touch, we will apply a small directed impulse to the bird’s physicsbody. You wouldn’t believe how easy this is with SpriteKit. Just add one line to the touchesBeganmethod:

The result should look like that:

7 [self addChild:dummy];

1 self.physicsWorld.gravity = CGVectorMake( 0.0, -5.0 );

1234

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { /* Called when a touch begins */ [_bird.physicsBody applyImpulse:CGVectorMake(0, 8)];}

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

8 de 26 18/02/14 19:32

Page 9: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

While we’re at it, we can also change the bird’s rotation depending on it’s velocity. If it’s flying upwardthe beak should point to the top right; if downward, to the bottom right. This can easily happen on aper-frame basis in the update:currentTime method, which was unused up to now.

As you can see, I use the bird’s physics body velocity property which is maintained by the physicssimulation. I added a little helper function clamp which avoids too large values in either direction. Notethat the minimum and maximum values (-1, 0.5) are radians.

Pipes

The last game entity are the pipes which are moving in to the scene from the right and need to beavoided. As before, the pipes are textured SKSpriteNodes, they will be animated using SKActions andthey’ll get a physics body attached for collision.

Add the two pipe graphics Pipe1.png and Pipe2.png to the project. From a graphical perspective, thepipes are a special entity. While the ground and skyline are always attached to the bottom edge of thescreen and the bird always has the same dimensions, the top pipe has to extend from the top edge and thebottom pipe has to extend from the bottom edge. While this could be solved programmatically with thebenefit of saving some texture space, I decided to use very high textures instead and not worry aboutdisplay size anymore.

123456789

1011121314

CGFloat clamp(CGFloat min, CGFloat max, CGFloat value) { if( value > max ) { return max; } else if( value < min ) { return min; } else { return value; }} -(void)update:(CFTimeInterval)currentTime { /* Called before each frame is rendered */ _bird.zRotation = clamp( -1, 0.5, _bird.physicsBody.velocity.dy * ( _bird.phy}

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

9 de 26 18/02/14 19:32

Page 10: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

While pipes consist of two SKSpriteNodes, I wrap both nodes into one empty SKNode as a parent. Thishas the advantage that it is sufficient to position the parent node in the world, while the two childs arepositioned relatively to their parent node, so I only need to worry about their vertical position.

The distance between the upper and lower pipe is arbitrary, I chose 100 points.

A pair of pipes is created outside of the right screen edge. The lower pipe’s position is chosen randomlysomewhere in the lower third of the screen. The upper pipe is added accordingly, considering the definedgap size. The zPosition for the pipes is chosen so that they always are rendered behind the ground.

12345

@implementation MyScene static NSInteger const kVerticalPipeGap = 100; -(id)initWithSize:(CGSize)size {

123456789

10111213141516171819202122

// Create pipes SKTexture* _pipeTexture1 = [SKTexture textureWithImageNamed:@"Pipe1"_pipeTexture1.filteringMode = SKTextureFilteringNearest;SKTexture* _pipeTexture2 = [SKTexture textureWithImageNamed:@"Pipe2"_pipeTexture2.filteringMode = SKTextureFilteringNearest; SKNode* pipePair = [SKNode node];pipePair.position = CGPointMake( self.frame.size.width + _pipeTexture1.size.widthpipePair.zPosition = -10; CGFloat y = arc4random() % (NSInteger)( self.frame.size.height / 3 ); SKSpriteNode* pipe1 = [SKSpriteNode spriteNodeWithTexture:_pipeTexture1];[pipe1 setScale:2];pipe1.position = CGPointMake( 0, y );pipe1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:pipe1.size];pipe1.physicsBody.dynamic = NO;[pipePair addChild:pipe1]; SKSpriteNode* pipe2 = [SKSpriteNode spriteNodeWithTexture:_pipeTexture2];[pipe2 setScale:2];

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

10 de 26 18/02/14 19:32

Page 11: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

The bird collides with the moving pipe and is pushed out of the screen.

We want these pipes to appear regularly. We will use SKActions again, but this time, in a little differentway. Instead of moving the pipes and resetting their position, we will spawn new pipes regularly. We willmove the spawn logic into a separate method. For that purpose, we need to store textures and theSKAction to move the pipes in new ivars:

The _moveAndRemovePipes action is created right after the pipe texture loading like so:

This will move the pipes by a full screen width plus two times their texture width to make sure that the

232425262728293031

pipe2.position = CGPointMake( 0, y + pipe1.size.height + kVerticalPipeGap );pipe2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:pipe2.size];pipe2.physicsBody.dynamic = NO;[pipePair addChild:pipe2]; SKAction* movePipes = [SKAction repeatActionForever:[SKAction moveByX:-1 y:0 dura[pipePair runAction:movePipes]; [self addChild:pipePair];

12345678

@interface MyScene () { SKSpriteNode* _bird; SKColor* _skyColor; SKTexture* _pipeTexture1; SKTexture* _pipeTexture2; SKAction* _moveAndRemovePipes;}@end

1234

CGFloat distanceToMove = self.frame.size.width + 2 * _pipeTexture1.size.width;SKAction* movePipes = [SKAction moveByX:-distanceToMove y:0 duration:0.01 * distanSKAction* removePipes = [SKAction removeFromParent];_movePipesAndRemove = [SKAction sequence:@[movePipes, removePipes]];

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

11 de 26 18/02/14 19:32

Page 12: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

pipes are out of sight. Then, they are removed from the scene.

The spawn method is responsible for creating new pipes:

Finally, we need to ensure that the spawnPipes method is called regularly to produce new pipes andattach the animation to it. This happens with an SKAction which is directly attached to the SKScene.

This action calls the spawnPipes method, then pauses for two seconds, then repeats.

Now we’ve got beautiful repeating pipes.

123456789

10111213141516171819202122232425

-(void)spawnPipes { SKNode* pipePair = [SKNode node]; pipePair.position = CGPointMake( self.frame.size.width + _pipeTexture1.size.w pipePair.zPosition = -10; CGFloat y = arc4random() % (NSInteger)( self.frame.size.height / 3 ); SKSpriteNode* pipe1 = [SKSpriteNode spriteNodeWithTexture:_pipeTexture1]; [pipe1 setScale:2]; pipe1.position = CGPointMake( 0, y ); pipe1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:pipe1.size]; pipe1.physicsBody.dynamic = NO; [pipePair addChild:pipe1]; SKSpriteNode* pipe2 = [SKSpriteNode spriteNodeWithTexture:_pipeTexture2]; [pipe2 setScale:2]; pipe2.position = CGPointMake( 0, y + pipe1.size.height + kVerticalPipeGap ); pipe2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:pipe2.size]; pipe2.physicsBody.dynamic = NO; [pipePair addChild:pipe2]; [pipePair runAction:_movePipesAndRemove]; [self addChild:pipePair];}

12345

SKAction* spawn = [SKAction performSelector:@selector(spawnPipes) onTarget:self];SKAction* delay = [SKAction waitForDuration:2.0];SKAction* spawnThenDelay = [SKAction sequence:@[spawn, delay]];SKAction* spawnThenDelayForever = [SKAction repeatActionForever:spawnThenDelay];[self runAction:spawnThenDelayForever];

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

12 de 26 18/02/14 19:32

Page 13: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

Collision detection and response

The game is over when the bird hits a pipe, so detecting a hit is our next challenge. SpriteKit provides adedicated delegate for collision detection, SKPhysicsContactDelegate, which allows to respondwhenever two physics entities are in contact. We will implement the delegate in our scene and set thephysics world delegate to the scene.

Moreover, we need to setup some categories for the different types of entities in the scene. Right now, allentities collide with each other and we would receive notifications for all these contacts because of thedefault setup: all relevant properties – discussed below – have value 0. We will use the categories toconfigure the contact testing in more detail.

123456789

101112131415161718192021

@interface MyScene () <SKPhysicsContactDelegate> { SKSpriteNode* _bird; SKColor* _skyColor; SKTexture* _pipeTexture1; SKTexture* _pipeTexture2; SKAction* _movePipesAndRemove;}@end @implementation MyScene static const uint32_t birdCategory = 1 << 0;static const uint32_t worldCategory = 1 << 1;static const uint32_t pipeCategory = 1 << 2; static NSInteger const kVerticalPipeGap = 100; -(id)initWithSize:(CGSize)size { if (self = [super initWithSize:size]) { /* Setup your scene here */

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

13 de 26 18/02/14 19:32

Page 14: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

We can use the categories to configure which entities can collide with each other and for which types ofcollisions we want to get notified. This is useful for two reasons: 1. the physics engine doesn’t need totest for collisions between e.g. the pipes and the ground (which saves some performance) and 2. we don’trequire notifications for all possible types of collisions.

SpriteKit provides three physics body properties for that purpose: categoryBitMask says to whichcategories an entity belongs, collisionBitMask says which categories can collide with the entity andcontactTestBitMask says which contacts lead to a notification. Note the separation of collision (actualinteraction with the physics world) and contact (sole collision testing without any reaction in the physicsworld)! The latter two fields allow to produce three different scenarios: 1. contacts between entities areignored, 2. contacts are notified but nothing happens in the physics simulation, 3. contacts are notifiedand applied to the physics world.

We will setup the bird as follows:

This means that the bird can collide with entities of the worldCategory and pipeCategory and that wewould get notified for both of them. (You may wonder why we separate the categories for world andpipes – we could use one category for both of them. I’ll clarify later in this tutorial.)

The definition for the ground entity is a little easier. We only need to assign the category but do notrequest any collision notification/reaction.

For the player nothing has changed: the bird still collides with the world. But the internals are nowconfigured in a more sensible way.

Now we need to implement the contact notification method as required by the delegate. In order tovisualize the collision, we will flash the background a little. That’s why we stored the sky color at thebeginning of the tutorial!

We’re using a symbolic identifier for the SKAction here for the first time. That way, we can remove anypreviously created SKAction with the same name.

2223

self.physicsWorld.gravity = CGVectorMake( 0.0, -5.0 ); self.physicsWorld.contactDelegate = self;

123

_bird.physicsBody.categoryBitMask = birdCategory;_bird.physicsBody.collisionBitMask = worldCategory | pipeCategory;_bird.physicsBody.contactTestBitMask = worldCategory | pipeCategory;

1 dummy.physicsBody.categoryBitMask = worldCategory;

12

pipe1.physicsBody.categoryBitMask = pipeCategory;pipe1.physicsBody.contactTestBitMask = birdCategory;

12

pipe2.physicsBody.categoryBitMask = pipeCategory;pipe2.physicsBody.contactTestBitMask = birdCategory;

123456789

- (void)didBeginContact:(SKPhysicsContact *)contact { // Flash background if contact is detected [self removeActionForKey:@"flash"]; [self runAction:[SKAction sequence:@[[SKAction repeatAction:[SKAction sequence self.backgroundColor = [SKColor redColor]; }], [SKAction waitForDuration:0.05], [SKAction runBlock:^{ self.backgroundColor = _skyColor; }], [SKAction waitForDuration:0.05]]] count:4]]] withKey:@"flash"}

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

14 de 26 18/02/14 19:32

Page 15: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

When you start the game now, you’ll see the background flashing red in case of a collision.

Animation stop

In order to stop the world movement and disable player control of the bird in case of a collision, we canmake use of the speed property of the SKNodes. Setting the speed to 0 means that all running SKActionsare paused. In order to avoid setting the speed property on every individual moving entity in the scene,we create a dummy parent node called _moving which holds all moving entities: the pipes, thebackground, the ground.

Once again we use an ivar to make it accessible from all methods.

The entity is created at the beginning and added to the scene. All moving entities are added to this parentnode.

123456789

@interface MyScene () <SKPhysicsContactDelegate> { SKSpriteNode* _bird; SKColor* _skyColor; SKTexture* _pipeTexture1; SKTexture* _pipeTexture2; SKAction* _movePipesAndRemove; SKNode* _moving;}@end

123456789

101112131415161718192021222324252627282930

_skyColor = [SKColor colorWithRed:113.0/255.0 green:197.0/255.0 blue:207.0/255.0 [self setBackgroundColor:_skyColor]; _moving = [SKNode node];[self addChild:_moving]; SKTexture* birdTexture1 = [SKTexture textureWithImageNamed:@"Bird1"birdTexture1.filteringMode = SKTextureFilteringNearest; ... [_moving addChild:_bird]; // Create ground ... for( int i = 0; i < 2 + self.frame.size.width / ( groundTexture.size.width * 2 ); ... [_moving addChild:sprite];} // Create skyline ... for( int i = 0; i < 2 + self.frame.size.width / ( skylineTexture.size.width * 2 ) ... [_moving addChild:sprite];}

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

15 de 26 18/02/14 19:32

Page 16: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

This affects also the pipe creation:

Now that we have all moving parts except the bird under one parent node. In order to stop animations,we can set the speed of _moving to 0 in case of contact. The parent’s speed is applied to all child nodes.We also want to happen this exactly once. We’re not interested in any further contacts once the animationhas halted, so we wrap the whole method in a corresponding if.

You might have noticed that we did not add the bird to the _moving node. This is because we still want itto move and animate. We just need to retain player control from the bird by allowing touches only with_moving.speed > 0.

123456

-(void)spawnPipes { ... [pipePair runAction:_movePipesAndRemove]; [_moving addChild:pipePair];}

1234567

- (void)didBeginContact:(SKPhysicsContact *)contact { if( _moving.speed > 0 ) { _moving.speed = 0; // Flash background if contact is detected ... }

123456

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { /* Called when a touch begins */ if( _moving.speed > 0 ) { [_bird.physicsBody applyImpulse:CGVectorMake(0, 8)]; }}

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

16 de 26 18/02/14 19:32

Page 17: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

Restart

Before we can restart the game, we need some way to reset the entire scene: the bird has to be moved toits initial position, its physics properties have to be reset, existing pipes have to be removed and theanimation has to be restarted. Most importantly, this shouldn’t start immediately after a collision but aftera little delay and an explicit user click/touch.

Let’s keep track when the user is allowed to restart the game in a new ivar _canRestart.

We will initialize this flag to NO because it’s not relevant during a running game.

But we’ll change the flag to YES after a collision and after the background-flash-animation has finished(that should be enough game-over-drama for the sake of this tutorial). For that purpose, we can useanother kind of SKAction, one that supports block execution. We simply append it to the flash-animation.

Now, if the game finished due to a collision and the user is allowed to restart, we can simply make use ofthe flag in the touchesBegan method and reset the scene after click/touch.

123456789

10

@interface MyScene () <SKPhysicsContactDelegate> { SKSpriteNode* _bird; SKColor* _skyColor; SKTexture* _pipeTexture1; SKTexture* _pipeTexture2; SKAction* _movePipesAndRemove; SKNode* _moving; BOOL _canRestart;}@end

1234567

-(id)initWithSize:(CGSize)size { if (self = [super initWithSize:size]) { /* Setup your scene here */ _canRestart = NO; self.physicsWorld.gravity = CGVectorMake( 0.0, -5.0 );

123456789

10111213

- (void)didBeginContact:(SKPhysicsContact *)contact { _moving.speed = 0; // Flash background if contact is detected [self removeActionForKey:@"flash"]; [self runAction:[SKAction sequence:@[[SKAction repeatAction:[SKAction sequenc self.backgroundColor = [SKColor redColor]; }], [SKAction waitForDuration:0.05], [SKAction runBlock:^{ self.backgroundColor = _skyColor; }], [SKAction waitForDuration:0.05]]] count:4], [SKAction runBlock:^{ _canRestart = YES; }]]] withKey:@"flash"];}

12345

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { /* Called when a touch begins */ if( _moving.speed > 0 ) { [_bird.physicsBody applyImpulse:CGVectorMake(0, 8)]; } else if( _canRestart ) {

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

17 de 26 18/02/14 19:32

Page 18: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

But wait, where’s that resetScene method coming from? Right, we still need to implement it.

How would we do that? We can easily reset the bird, restart the animation and reset the _canRestartflag, but how can we reset the pipes? Right now the existing pipes are direct children of the _movingcontainer and we have no way to easily distinguish them from other nodes like the ground or skyline.

In order to easily access the pipes and remove them from the scene, we will restructure the scenehierarchy one more time: We will introduce another artificial parent node for all pipes, add this node tothe existing _moving node and add all pipes to this new parent node.

The change is pretty straightforward. Once again a new ivar…

…and a new SKNode as the parent for the pipes…

…and all created pipes added to this node instead of the _moving node.

Now we have everything we need to implement the resetScene method:

678

[self resetScene]; }}

123456789

1011

@interface MyScene () <SKPhysicsContactDelegate> { SKSpriteNode* _bird; SKColor* _skyColor; SKTexture* _pipeTexture1; SKTexture* _pipeTexture2; SKAction* _movePipesAndRemove; SKNode* _moving; SKNode* _pipes; BOOL _canRestart;}@end

12345678

_moving = [SKNode node];[self addChild:_moving]; _pipes = [SKNode node];[_moving addChild:_pipes]; SKTexture* birdTexture1 = [SKTexture textureWithImageNamed:@"Bird1"birdTexture1.filteringMode = SKTextureFilteringNearest;

1234

[pipePair runAction:_movePipesAndRemove]; [_pipes addChild:pipePair];}

123456789

-(void)resetScene { // Move bird to original position and reset velocity _bird.position = CGPointMake(self.frame.size.width / 4, CGRectGetMidY(self.fr _bird.physicsBody.velocity = CGVectorMake( 0, 0 ); // Remove all existing pipes [_pipes removeAllChildren]; // Reset _canRestart

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

18 de 26 18/02/14 19:32

Page 19: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

A little more drama

Right now, a crashed bird would simply fall as far as the physics world permits. If it crashes right in apipe gap, it would possibly land directly on the lower pipe. I thought a little more drama was due! Iwanted to ensure that the bird falls down to the ground and I wanted it to look a little more spectacular.So I changed the bird’s collision bitmask after collision so that it only would collide with the ground, andI added a little rotation animation:

The angle and duration calculations are attempts to adjust the amount of rotation to the bird’s altitude. Ifthe bird collides at a very low position, it will hit the ground sooner than if it collides at a high position,so the angle and durations are smaller if the bird flew lower. Right after the animation we change thebird’s speed to 0, too, to halt the wing flap animation. To avoid overriding the animation, we need torestrict the velocity-dependent rotation to when the game is still running:

Now we need to reset the collisionBitMask, speed and zRotation properties in the resetScenemethod as well:

An idea to make the crash even more spectacular would be to add a little feather particle system. Butmaybe that’s something for another tutorial.

Score counting

To be continued…

Conclusion

1011121314

_canRestart = NO; // Restart animation _moving.speed = 1;}

12345678

- (void)didBeginContact:(SKPhysicsContact *)contact { _moving.speed = 0; _bird.physicsBody.collisionBitMask = worldCategory; [_bird runAction:[SKAction rotateByAngle:M_PI * _bird.position.y * 0.01 durati _bird.speed = 0; }];

123456

-(void)update:(CFTimeInterval)currentTime { /* Called before each frame is rendered */ if( _moving.speed > 0 ) { _bird.zRotation = clamp( -1, 0.5, _bird.physicsBody.velocity.dy * ( _bird. }}

1234567

-(void)resetScene { // Reset bird properties _bird.position = CGPointMake(self.frame.size.width / 4, CGRectGetMidY(self.fra _bird.physicsBody.velocity = CGVectorMake( 0, 0 ); _bird.physicsBody.collisionBitMask = worldCategory | pipeCategory; _bird.speed = 1.0; _bird.zRotation = 0.0;

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

19 de 26 18/02/14 19:32

Page 20: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

During the course of this tutorial, you’ve learned how to…

create a SpriteKit project with Xcodeload textures into SKTexturecreate sprites with SKSpriteNodeuse different animation speeds to create the illusion of depthuse the SKSpriteNode‘s zPosition property to control rendering orderattach and configure physics bodies to nodesconfigure the physics worlduse SKAction to animate sprites, move the game world and control game statescontrol game flow using the SKNode.speed propertyhandle touchesdetect collisionsstructure the scene graph in a way that makes sense for the game world

If you think that something needs to be covered in more detail, feel free to leave a comment or contactme on Twitter (@digitalbreed). I will try to update the tutorial or respond to you directly.

If you liked this tutorial and you have some Bitcoins to spare, I would appreciate a tip at1QByEN4aeEN1KKqikBFUGdgeg1ZCX6c1nr.

Download

I have pushed the tutorial code to GitHub.

22 Comments

Got something to say? Feel free, I want to hear from you! Leave a Comment

Mat says:2/15/2014 at 5:51 ·

Great Tutorial, i’ve learned allot about the ios sprite kit from this.Keep up the good work :)

1.

Ryyydizzle says:2/16/2014 at 2:18 ·

Is it difficult to add a main menu to this game?

2.

Mike says:2/16/2014 at 6:36 ·

Great work and it’s very useful for me who is just starting to learn the sprite kit. But where i candownload the source code? i can’t find out the link.

3.

4.

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

20 de 26 18/02/14 19:32

Page 21: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

Darrell says:2/16/2014 at 15:40 ·

I would like to download the image assets for this tutorial. It says at the top they can bedownloaded with the rest of the project. Where can I find them?

Thanks, it looks like a great tutorial.

Fedor says:2/16/2014 at 16:12 ·

Great!I would like to download images. Please live linkThanks for your work

5.

matt says: (Author)2/16/2014 at 20:10 ·

I have pushed the tutorial code to GitHub, link is at the bottom of the tutorial.

6.

Mark says:2/17/2014 at 1:10 ·

When are you putting the score counting part of the tutorial up?

7.

Syrinathos says:2/17/2014 at 7:34 ·

Absolutely love the tutorial! Though there were some various problems throughout thewalk-through (e.g., differently named variables (I think you listed groundTexture as“bottomTexture” at one point), missing bits of code, etc.)., it was an excellent read, and I’m goingto take a lot away from it.

Thank you!

8.

matt says: (Author)2/17/2014 at 10:17 ·

@Ryyydizzle, not really. This tutorial is about the game mechanics but I may extend it with somemenu code.

@Mark, as soon as time permits. The basic concept will be: add an invisible rectangular physics

9.

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

21 de 26 18/02/14 19:32

Page 22: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

object with it’s own category right of each pipe pair and increment the score every time a contactwith this object is detected.

@Syrinathos, thanks, fixed. I did some renaming before I wrote the tutorial and I missed that one.Any other issues you’ve encountered?

Sascha says:2/17/2014 at 15:56 ·

I’d recommend adding ‘_bird.physicsBody.velocity = CGVectorMake(0, 0);’ to touchesBegan.Otherwise the impulse gets added to the current velocity of the bird node, leading to bigger jumpsthe more often you tap.

10.

ET Worker says:2/17/2014 at 18:53 ·

I like your code, especially the _moving part and animation!

One more question, if I tap more than once quickly, the bird seems run very high …Do you know how to adjust the gravity and impulse so that the bird running normally?

thanks!

11.

matt says: (Author)2/17/2014 at 19:12 ·

@ET Worker, please see Sascha’s comment right above yours for a solution.

12.

Daniel Bocksteger says:2/17/2014 at 20:58 ·

Hey Matt, did you spend any thought about counting the pipes the bird had been reached? It isn’tgoing into my mind how to realize this…

Thanks for this great Tutorial! :-)

13.

matt says: (Author)2/17/2014 at 21:00 ·

@Daniel Bocksteger, yes, I already sketched a solution above, see my response to Mark. I willpossibly add it later tonight.

14.

15.

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

22 de 26 18/02/14 19:32

Page 23: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

Syrinathos says:2/18/2014 at 1:08 ·

@Matt: Not as far as I can recall, no. The only other one that stood out in my mind was the_movePipesAndRemove having been different between one block of code and the next, but youseem to have fixed that as well.

In addition, another item that wasn’t covered was the lack of a distinct ceiling within the gameworld. As the project stands now, the player can simply fly over all the pipes and not have to worryabout collisions of any kind. I made a crude work around by ensuring that they cannot apply theimpulse if the Y position of the bird is within 100 points of the top of the screen, but if they tapquickly enough they can still fly up into the ceiling until gravity yanks them back down.

I’m thinking another invisible node running along the top of the scene moving with the bird tocount as another physics body would be in order.

Regarding the score counting, wouldn’t it be easier to make an instance variable that getsincremented as each pipe is removed from the scene? Logically speaking, if the pipe has beenremoved, you’ve already passed it.

Adam says:2/18/2014 at 7:42 ·

how much longer until the score part is added?great tutorial BTW :)

16.

matt says: (Author)2/18/2014 at 10:07 ·

@Syrinathos, yes, I discussed the ceiling issue on Twitter, too, and I will add some information onhow to avoid that. Score counting would be easier that way but it would cause a recognizabledelay, too.

17.

Ian says:2/18/2014 at 10:33 ·

@Syrinathos: Regarding the bird flying off the screen, simply restrict the bird to the self.frame orin other words restrict it to the frame of the phone.

About the score counting, its very easy to implement, like @matt said, all you need to do add anSKNode to between the pipes and make a collision category for it. When the bird collides with theSKNode, just increment the score.

@matt: Great tutorial! Love the way you have explained everything in detail with illustrations ofthe progress. Keep up the good work!

18.

19.

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

23 de 26 18/02/14 19:32

Page 24: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

qiangLi says:2/18/2014 at 11:12 ·

Thanks for share,it is help me alot!

Nico says:2/18/2014 at 16:17 ·

Hey, i have added the line _bird.physicsBody.velocity = CGVectorMake(0, 0);in the method touchesBegan:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{/* Called when a touch begins */if( _moving.speed > 0 ){[_bird.physicsBody applyImpulse:CGVectorMake(0, 8)];_bird.physicsBody.velocity = CGVectorMake(0, 0);}else if( _canRestart ){[self resetScene];}}

but it takes no effect.

can someone help me?sry for my bad english, i am a german :D

20.

matt says: (Author)2/18/2014 at 16:21 ·

@Nico, do it the other way around. First set the velocity to 0, then apply the impulse.

21.

Nico says:2/18/2014 at 16:30 ·

thanks!! now it worksbut i have to change the impule from 8 to 4. now its perfect!

22.

Leave a Comment

Let me know your thoughts on this post but remember to place nicely folks!

Name

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

24 de 26 18/02/14 19:32

Page 25: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

Email (never published)

Website

Submit Comment

← LeWeb 2010 startups revisited

Recent Comments

Nico on How to build a game like Flappy Bird with Xcode and SpriteKitmatt on How to build a game like Flappy Bird with Xcode and SpriteKitNico on How to build a game like Flappy Bird with Xcode and SpriteKitqiangLi on How to build a game like Flappy Bird with Xcode and SpriteKitIan on How to build a game like Flappy Bird with Xcode and SpriteKitmatt on How to build a game like Flappy Bird with Xcode and SpriteKitAdam on How to build a game like Flappy Bird with Xcode and SpriteKitSyrinathos on How to build a game like Flappy Bird with Xcode and SpriteKitmatt on How to build a game like Flappy Bird with Xcode and SpriteKitDaniel Bocksteger on How to build a game like Flappy Bird with Xcode and SpriteKit

Categories

1984 (3)Book Reviews (1)deutsch (3)Entrepreneurship (2)Game Development (55)Hardware (6)Linkdump (1)Links (2)Mac (3)Miscellaneous (26)Music (1)Personal (35)Side Thoughts (19)Software Engineering (50)

About

Matthias Gall is a software architect turned entrepreneur with a degree in Computer Science and morethan 10 years of professional software development experience. Matthias is co-founder of trimplement, asoftware development and consulting firm and several other stealth(*) projects.

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

25 de 26 18/02/14 19:32

Page 26: How to Build a Game Like Flappy Bird With Xcode and SpriteKit | Digitalbreed

(* euphemism for never ending stories)

From the Blog

How to build a game like Flappy Bird with Xcode and SpriteKit2/10/2014 · 22 Comments

This is a developing blog post. Keep coming back to see it progressing. When I heard about Flappy Birdfor the first time, the hype was already in its final …

LeWeb 2010 startups revisited11/18/2013 · No Comments

Around the same time in 2011, I wrote a posting about the LeWeb 2010 finalists and startup success ingeneral. I placed a reminder into my calendar to revisit the …

Tomcat 7 and Nginx on Ubuntu 10.123/13/2013 · No Comments

Earlier last week, I installed Nginx with a Tomcat on my Ubuntu VPS. I decided to give the “APR basedApache Tomcat Native library” a try. Here’s what I did.

LATEST TWEETS

Unique blog visitors 5000% above average. Seems like the tutorial hits a nerve. 09:27:43 PMFebruary 17, 2014

Follow Follow @digitalbreed@digitalbreed 200 followers

Tags

3d airport android Arcadia camera charts cheat sheet clickjacking connection timeout eclipse facebook flattr galileo gamedevGame Development google GORM grails groovy GWT innovation java JavaScript Mac MongoDB osx security software

Startups tools

I'm also on Twitter, Facebook & MobyGames. My professional profiles are on Xing and LinkedIn.

How to build a game like Flappy Bird with Xcode and SpriteKi... http://digitalbreed.com/2014/how-to-build-a-game-like-flappy...

26 de 26 18/02/14 19:32