The Complete iOS Game Course - Build a Flappy Bird Clone
4.7 (76 ratings)
Instead of using a simple lifetime average, Udemy calculates a course's star rating by considering a number of different factors such as the number of ratings, the age of ratings, and the likelihood of fraudulent ratings.
5,224 students enrolled
Wishlisted Wishlist

Please confirm that you want to add The Complete iOS Game Course - Build a Flappy Bird Clone to your Wishlist.

Add to Wishlist

The Complete iOS Game Course - Build a Flappy Bird Clone

Over 350+ videos taking you step-by-step through process of building 8+ different applications using Sprite Kit
4.7 (76 ratings)
Instead of using a simple lifetime average, Udemy calculates a course's star rating by considering a number of different factors such as the number of ratings, the age of ratings, and the likelihood of fraudulent ratings.
5,224 students enrolled
Last updated 7/2014
English
Price: $20
30-Day Money-Back Guarantee
Includes:
  • 30 hours on-demand video
  • 1 Article
  • Full lifetime access
  • Access on mobile and TV
  • Certificate of Completion
What Will I Learn?
  • Build iOS Games using Sprite Kit
  • Use the Objective-C language to build iOS games
  • Understand game physics and mechanics
View Curriculum
Requirements
  • Familiarity with object-oriented programming (does not need to be Objective-C)
  • An intel-based Mac that has Mac OS X Snow Leopard or later installed
Description

We built an immersive game development course that teaches you all of the fundamentals so you can build your own games on iPhones and iPads. We combine videos, notes, collaborative discussion forums, and challenging assignments to have students build real apps. Teaching online is not new to us. Our highly successful Beginner iOS Bootcamp (over 18k students and 5 star review) teaches students the basics of programming iOS apps. We use the same proven pedagogy to teach game development.

The course will include over 120 hours of content (30 hours of video plus notes and challenges), an active discussion forum where students and teachers answer questions, and multiple fully coded example projects that you can download.

Topics covered:

  • Introduction to Game Development , Sprite Kit , Scenes and Nodes, Coordinates, Game Loop
  • Sprite/Texture Creation, Sprite Theory, Atlas Files
  • Animation, Parallax Scrolling, Character animation
  • Physics Bodies, Physics Properties, Bit Fields, Collisions, Contact Response
  • User Input, Input Handler
  • Character Movement/Physics, State machines, Player Physics, Jump Curve, Double Jump, Boost, etc.
  • Tile Based Game World, Tile Sprites, Tiled + Kobold Kit, Creating and Loading Tiled files
  • Collision Detection, Axis Alined Bounding Box, Collision Bit Masks
  • Obstacles & Enemies, Basic Enemy AI
  • Collectables, Power Ups
  • Effects, Particle Effects
  • Sound, Adding Music, Adding Sound Effects
  • Scoring, HUD, Stats/Progress Tracking, Score Board
  • Game Menus, Saving/Loading Game Progression

Reviews from our iOS course

"I must say that so far, this course is awesome. Having the challenging assignments, daily discussions and feedback from the instructors, has been the missing piece that I have been looking for. I have read a handful of books, watched hours of video & typed in a bunch of tutorials, and finally, having to work through tough assignments and applying what I have been learning, it is all starting to click - Finally!" - Mark S.

“Code Coalition's discussion board is one of the best resources for a beginning iOS developer. So much help being offered” - Omar S.

“I've just completed the iOS101 course, which I thought was a great intro to the XCode environment... I feel it's been well worth the investment. ” - Herdy H.

"Wow, @CodeCoalition! Moving quickly! Week 2 is so different than week 1...and I like it :) Thnx for the challenge" - Melissa B.

“Just discovered @CodeCoalition! An excellent resource for anyone who wants to make their first iPhone app.” -Novall K.

“Can't reiterate it enough how this course is helping me with my iOS dev skills. I think using protocols and delegation is finally becoming second nature. Fingers crossed :-)” -Alex P.

“I am really loving the class. I have taken classes at Code School & Treehouse and both were missing a key element. The ability to ask questions as you complete a section and get an answer. “ -Lisa A.

“Your training is the best out there so far. I wish I had the time away from regular job to follow along.” -Christian S.

“Im loving this.. I have been through at least 5 books, and many online deals. Yours is super so far. Finally, i can get from start to finish on a lesson without wondering why on "Everything" thank youCant wait to do more.. “ -Kevin R.

Why take this course and how much time does it take to complete?

iOS game development, and software development as a whole, is a booming career. The demand for new developers at all levels far outweighs the supply. Barrier to entry is not as high as one would think - though passion and hard work are necessary, a degree in computer science or any other technical field is not required.

We aim to take you from complete beginner to junior game developer in three months. The apps you create in this course can be used on your portfolio so you have something to show when you apply for jobs. Not only that, you can throw your apps on the app store and be the next Flappy Bird!

Who is the target audience?
  • Novice or advanced programmers who are interested in game development
  • Game programmers from other languages/frameworks
Students Who Viewed This Course Also Viewed
Curriculum For This Course
Expand All 349 Lectures Collapse All 349 Lectures 30:22:14
+
Sprite Kit Concepts
10 Lectures 58:25

Project Repositories and Resources

We will be posting additional course information here. During the course if you find yourself unable to get a bit of code to work you can find the completed code repositories here:

Main Space Cannon repo:

Bomb power up challenge:

Multi power up challenge:

Music On/Off button challenge:

Bouncing Ball challenge:

Alien Animation Challenge:

Scrolling Challenge:

Tappy Plane:

Preview 01:38

Nodes

Code

In this video, we use the following code to update the spaceship's rotate action to instead make it move forward:

SKAction *action = [SKAction moveByX:0.0f y:200.0f duration:1];
Links

Apple's introduction to Sprite Kit: Sprite Kit Programming Guide: About Sprite Kit

Preview 08:57

A Closer Look at Nodes

In this video we talk about nodes in a bit more detail. We discuss a few of the different types of nodes that Sprite Kit makes available to us as well as many of the properties and methods that make up the SKNode class. We run through an example of creating a colored rectangle using SKSpriteNode and see how adding it as a child to different nodes in our node tree affects how it behaves.

Links

* SKNode Class Reference

A Closer Look At Nodes Part 1
06:54

A Closer Look At Nodes

In this video we talk about nodes in a bit more detail. We discuss a few of the different types of nodes that Sprite Kit makes available to us as well as many of the properties and methods that make up the SKNode class. We run through an example of creating a colored rectangle using SKSpriteNode and see how adding it as a child to different nodes in our node tree affects how it behaves.

Links

* SKNode Class Reference

A Closer Look At Nodes Part 2
04:44

Adding Images to Projects

This video is just a refresher on how to add images to your Xcode projects. If you are familiar with doing this then you may want to skip this video. Graphics are a big part of games, and so we'll often be adding images to our projects throughout the course. Whenever we add new images in a video, you'll be able to find the images featured in that video for download as part of that video's notes.

* Space Backgrounds by Rawdanitsu

Adding Images to Projects
05:21

Coordinates

Having a solid understanding of how your game assets are positioned within the coordinate systems of the various nodes and scenes within your game is important for developing code that does exactly what you expect it to. In this video we explore how nodes can effect each others positions depending on how they are organised in the hierarchy of your scene's node tree and we look at how we can make adjustments to the coordinate systems of our nodes by changing the AnchorPoint property.

Be sure that you understand the positioning relationships between nodes by spending a bit of time playing with them. Try building up a node tree with a number of levels by adding nodes as children of children. Notice how this effects the order in which your nodes are drawn. Also note that position and rotation are not the only properties that a node passes along to its descendants. Other properties that are passed down the tree include scale, alpha, hidden and speed.

Suggested Exercise

Change the action on the spaceship back to the original rotation action of the default Sprite Kit template and then see if you can adjust the anchor point of the spaceship and positions of the flame nodes such that the spaceship rotates around its nose with its flames still in the correct positions.

Code

In this video we use the following code to add the two flames to our spaceship:

SKSpriteNode *leftFlame = [SKSpriteNode spriteNodeWithImageNamed:@"Flame"];
leftFlame.position = CGPointMake(-12, -109);
[sprite addChild:leftFlame];
SKSpriteNode *rightFlame = [SKSpriteNode spriteNodeWithImageNamed:@"Flame"];
rightFlame.anchorPoint = CGPointMake(0.5, 1.0);
rightFlame.position = CGPointMake(12, -87);
[sprite addChild:rightFlame];

Links

Apple's documentation on coordinates, anchor points, node tree, draw order, etc. Well worth having a glance at: Sprite Kit Programming Guide: Building Your Scene

Coordinates
11:04

A Closer Look at Anchor Points

In this video we discuss anchor points in a bit more detail and experiment with some code in the standard Sprite Kit template to see how changing the anchor point property of the space ship, alters the positioning of the sprite image and affects how it rotates.

A Closer Look at Anchor Points
06:20

Game Loops

The game loop is at the core of just about every game. The state of our game needs to be updated over time, and the game loop is responsible for driving this process. Our game loop will run once per frame of animation and each time it runs we need to process all aspects of our game, e.g. player input, artificial intelligence, physics, scoring etc. When developing games, getting into the mindset of the game loop can help when thinking about how to solve certain problems as it's important that we know when different events will occur throughout the processing of a frame. Developing a solid game loop can be challenging, and fortunately, Sprite Kit has already done that work for us and so we don't need implement our own game loop. In this video we have a quick look at the Sprite Kit game loop and see how different aspects of our game state are processed throughout a frame.

Links

A breakdown of how a Sprite Kit scene processes a frame of animation: Sprite Kit Programming Guide: Advanced Scene Processing

An in depth discussion of game loops as a pattern. In Sprite Kit the design of the game loop has already been done for us, so this link only serves as further (somewhat advanced) reading if you are interested: Game Programming Patterns: Game Loop

Game Loops
04:06

Overview of Actions

Actions in Sprite Kit allow us to relatively easily add movement and animation to the nodes in our game. In this video we discuss actions and the tasks things we can use them for and how we implement them.

Overview of Actions
06:24

Performance

The performance of our game is obviously important, as we want our games to run as smoothly as possible. In order to make sure that we're achieving this goal, we need some sort of benchmark that we can keep track of. The frame rate is the most fundamental benchmark we can use for this purpose. If we see our frame rate drop when a particularly complex event occurs in our game, it could be a clue to us that we might need to do some optimizing in that area. Sprite Kit can report the frame rate to us along with a couple of other basic pieces of diagnostic information about how our scene is being processed. In this video we'll have a quick discussion how this info can help us when considering our game's performance.

Diagnostics
02:57
+
Our First Game! Build a Space Cannon Shooter
7 Lectures 44:41

Our First Game

With the basics out of the way, it's time to get stuck into creating a real game! Over the next couple of sections we are going to produce a physics based space shooter. We'll be covering a number of different concepts and Sprite Kit features along the way and at the end of it, you'll have a fun little game to play with. There'll be plenty of room for you to expand the game as well, if you'd like to take it further.

Code

In this video we declare two class level variables:

SKNode *_mainLayer;
SKSpriteNode *_cannon;

We setup our cannon and get it rotating using the following code:

// Add background.
SKSpriteNode *background = [SKSpriteNode spriteNodeWithImageNamed:@"Starfield"];
background.position = CGPointZero;
background.anchorPoint = CGPointZero;
background.blendMode = SKBlendModeReplace;
[self addChild:background];
// Add main layer.
_mainLayer = [[SKNode alloc] init];
[self addChild:_mainLayer];
// Add cannon.
_cannon = [SKSpriteNode spriteNodeWithImageNamed:@"Cannon"];
_cannon.position = CGPointMake(self.size.width * 0.5, 0.0);
[_mainLayer addChild:_cannon];
// Create cannon rotation actions.
SKAction *rotateCannon = [SKAction sequence:@[[SKAction rotateByAngle:M_PI duration:2],
[SKAction rotateByAngle:-M_PI duration:2]]];
[_cannon runAction:[SKAction repeatActionForever:rotateCannon]];

Links

Not sure how radians work? Wikipedia has a nice little animated GIF that explains it well: Wikipedia: Radian

Space Cannon
09:39

Review: Space Cannon Setup

This video is a review of some of the code we've added to our Space Cannon game so far. We discuss SKSpriteNodes, instance variables, actions, SKScene and SKView.

Review: Space Cannon Setup
07:53

Making our Cannon Shoot

Time to get our cannon shooting. In order to do so, we are going to need to convert the rotation angle of our cannon into usable x and y coordinates. We can use good old trigonometry for this. In this video we'll create a helper method to convert our angle and setup a method to create a new cannon ball node every time we tap the screen.

Code

static inline CGVector radiansToVector(CGFloat radians)
{
CGVector vector;
vector.dx = cosf(radians);
vector.dy = sinf(radians);
return vector;
}
-(void)shoot
{
// Create ball node.
SKSpriteNode *ball = [SKSpriteNode spriteNodeWithImageNamed:@"Ball"];
CGVector rotationVector = radiansToVector(_cannon.zRotation);
ball.position = CGPointMake(_cannon.position.x + (_cannon.size.width * 0.5 * rotationVector.dx),
_cannon.position.y + (_cannon.size.width * 0.5 * rotationVector.dy));
[_mainLayer addChild:ball];
}

Links

Need to brush up on your sine and cosine? Wikipedia: Trigonometric Functions

Add shoot method
05:10

Working With Angles

In this video we discuss a few of the concepts we need to know when working with angles in our games. We discuss radians, the various constants we have available related to the value of pi, as well as the functions, sine and cosine.

Notes

We can convert degrees to radians using: radians = degrees * (π / 180)

We can convert radians to degrees using: degrees = radians * (180 / π)

Working With Angles
05:58

Data Types

In this video we discuss a number of the basic data types that we'll be regularly working with while developing games. We look at CGFloat, CGPoint, CGVector, CGSize, CGRect

Data Types
05:17

Adding Physics

To get our cannon balls moving, we can take advantage of Sprite Kit's physics simulation features. By adding a physics body to our cannon ball node and giving it a velocity, we can get things firing.

Code

In order to make our cannon balls shoot, we declare the following constant:

static const CGFloat SHOOT_SPEED = 1000.0;

And add physics to our cannon balls by adding to our shoot method:

ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:6.0];
ball.physicsBody.velocity = CGVectorMake(rotationVector.dx * SHOOT_SPEED, rotationVector.dy * SHOOT_SPEED);

We also turn off gravity for all nodes:

// Turn off gravity.
self.physicsWorld.gravity = CGVectorMake(0.0, 0.0);

Links

Sprite Kit Programming Guide: Simulating Physics

Add physics body
04:50

Shoot Method Review

This is a review video of the code we've set up for the shoot method of our Space Cannon game.

Shoot Method Review
05:54
+
Review of Shooting with our Space Cannon
6 Lectures 34:41

Keeping Things Clean

If we want to keep our game's performance smooth, it's a good idea to remove any nodes from our node tree that we're no longer using. By enumerating through the nodes in the tree, we can identify those that are out of bounds of the screen and go ahead and remove them from our scene.

Code

We set the name property on our ball nodes to make them easy to find:

ball.name = @"ball";

Then we override the didSimulatePhysics method, enumerate our nodes, and remove those we don't need.

-(void)didSimulatePhysics
{
// Remove unused nodes.
[_mainLayer enumerateChildNodesWithName:@"ball" usingBlock:^(SKNode *node, BOOL *stop) {
if (!CGRectContainsPoint(self.frame, node.position)) {
[node removeFromParent];
}
}];
}
Clean up
03:28

Using Breakpoints

In this video we look at how we can use breakpoints to interrupt the execution of our code and check the state of our game to help when debugging our code. If you are familiar with how to use breakpoints, feel free to skip this video. We also look at how we can use the output window to print out the values of properties of our objects.

Using Breakpoints
07:40

Review of Physics Body Basics

In this video we have a play with physics bodies. Starting with the standard Sprite Kit template project, we create a node to represent a soccer ball and get it moving around by creating a physics body for it. We see how the dynamic and affectedByGravity properties affect our node and discuss some of the different types of physics bodies.

Assets

* SoccerBall@2x.png

Links

* Soccer Ball by gothicfan95

Review of Physics Body Basics
07:37

Timing

As we process each new frame of our game's state, we need to consider the order in which things should be processed. In this video we see first hand how the timing of when we call our shoot method within the game loop, can have an impact on our gameplay.

Code

We delay the call of our shoot method by adding to the didSimulatePhysics method:

// Shoot.
if (_didShoot) {
[self shoot];
_didShoot = NO;
}

Links

Sprite Kit Programming Guide: Advanced Scene Processing

Timing
03:43

Review of Game Loop

In this video we take a closer look at methods update, didEvaluateActions and didSimulatePhysics that we have as part of our scene. We examine the timing of when these methods are called in regards to our game loop by using some log statements to see how the properties of a node changes each frame.

Links

* Advanced Scene Processing

Review of Game Loop
06:18

Edges and Physical Properties

In this video we add walls to our scene using a new physics body type: edge. Apple's documentaion describes an edge thus:

  • An edge is a static volume-less body. Edges are never moved by the simulation and their mass doesn’t matter. Edges are used to represent negative space within a scene (such as a hollow spot inside another entity) or an uncrossable, invisibly thin boundary. For example, edges are frequently used to represent the boundaries of your scene.
  • The main difference between a edge and a volume is that an edge permits movement inside its own boundaries, while a volume is considered a solid object. If edges are moved through other means, they only interact with volumes, not with other edges.

We also need to update a few of the properties on the physics bodies of our cannon balls so that they maintain their momentum when bouncing around:

  • The friction property determines the roughness of the body’s surface. It is used to calculate the frictional force that a body applies to other bodies moving along its surface.
  • The linearDamping and angularDamping properties are used to calculate friction on the body as it moves through the world. For example, this might be used to simulate air or water friction.
  • The restitution property determines how much energy a body maintains during a collision—its bounciness.

Code

We add edges for our cannon balls to bounce off by adding some new nodes in the init method:

// Add edges.
SKNode *leftEdge = [[SKNode alloc] init];
leftEdge.physicsBody = [SKPhysicsBody bodyWithEdgeFromPoint:CGPointZero toPoint:CGPointMake(0.0, self.size.height)];
leftEdge.position = CGPointZero;
[self addChild:leftEdge];
SKNode *rightEdge = [[SKNode alloc] init];
rightEdge.physicsBody = [SKPhysicsBody bodyWithEdgeFromPoint:CGPointZero toPoint:CGPointMake(0.0, self.size.height)];
rightEdge.position = CGPointMake(self.size.width, 0.0);
[self addChild:rightEdge];

We also adjust some physics properties on our cannon balls:

ball.physicsBody.restitution = 1.0;
ball.physicsBody.linearDamping = 0.0;
ball.physicsBody.friction = 0.0;

Links

There is much more info on the vairous aspects of Sprite Kit's physics simulation in Apple's documentation: Sprite Kit Programming Guide: Configuring the Physical Properties of a Physics Body

Adding Edges to the scene
05:55
+
Challenge 1: Bouncing Balls
4 Lectures 20:05
Challenge: Ball Challenge

The idea of this challenge is to play with physics bodies by creating a bouncing ball simulator. Create a new sprite kit project for the iPhone and setup the project in in portrait orientation. Set the background colour to white. Remove the code that comes with the template project that creates the hello world label and space ship nodes. Add code to the touches began event so that each time you tap on the screen a random ball is created at the location of the tap. The ball should automatically fall and bounce around inside the screen. You will need to setup a edge based physics body that loops around the border of the screen (hint: you can use the scene's frame when creating your physics body). You should have different types of balls (Choose at random each time there is a tap event) each with their own physics properties that make them behave differently from one another. There are graphics provided for 3 different types of balls:

* An 8 ball - this should be the heaviest and not bounce as much as the others.

* A soccer ball - a bit lighter than the 8 ball and more bouncy.

* A beach ball - this ball should be very light and bouncy.

Once you've setup the basic 3 balls, experiment with Sprite Kit's physics simulator by applying different physics properties.

Here are some suggestions for things to try:

* Make one of the balls bounce forever.

* Make one of the balls spin when it is created.

* See what happens when you turn off the friction for all the balls.

* See what happens when you set the friction to maximum for all the balls.

Assets

* 8Ball@2x.png

* BeachBall@2x.png

* SoccerBall@2x.png

Links

* Billiard Balls by FacadeGaikan

* Soccer Ball by gothicfan95

Challenge: Ball Challenge
01:16

Challenge: Ball Challenge: Solution

In this video we go through the solution to the ball challenge and have a bit of a play around with the properties of our physics bodies.

Code

Create a new Sprite Kit template project, add the 3 ball graphics to the project, and remove the code that generates the Hello World text and the code that creates a rotating spaceship node.

In the init method, change the background color to white:

self.backgroundColor = [SKColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];

In the init method, set up an invisible wall around the edge of the screen so that when we add some balls to the scene they will bounce around. Do this by creating an instance of SKNode that has an edge based physics body using the frame of the scene as the physics body's rectangle:

SKNode *edge = [SKNode node];
edge.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
[self addChild:edge];

Change the touchesBegan method to create a random ball when a touch event occurs. The 3 ball types should each have their own mass and restitution properties so that they bounce and affect each other in different ways:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
int random = arc4random_uniform(3);
SKSpriteNode *ball;
switch (random) {
case 0:
ball = [SKSpriteNode spriteNodeWithImageNamed:@"8Ball"];
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.size.width * 0.5];
ball.physicsBody.mass = 0.8;
ball.physicsBody.restitution = 0.2;
break;
case 1:
ball = [SKSpriteNode spriteNodeWithImageNamed:@"BeachBall"];
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.size.width * 0.5];
ball.physicsBody.mass = 0.1;
ball.physicsBody.restitution = 0.8;
break;
default:
ball = [SKSpriteNode spriteNodeWithImageNamed:@"SoccerBall"];
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.size.width * 0.5];
ball.physicsBody.mass = 0.4;
ball.physicsBody.restitution = 0.5;
break;
}
ball.position = location;
[self addChild:ball];
}
}
Challenge: Ball Challenge: Solution Part 1
04:11

Challenge: Ball Challenge: Solution

In this video we go through the solution to the ball challenge and have a bit of a play around with the properties of our physics bodies.

Code

Create a new Sprite Kit template project, add the 3 ball graphics to the project, and remove the code that generates the Hello World text and the code that creates a rotating spaceship node.

In the init method, change the background color to white:

self.backgroundColor = [SKColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];

In the init method, set up an invisible wall around the edge of the screen so that when we add some balls to the scene they will bounce around. Do this by creating an instance of SKNode that has an edge based physics body using the frame of the scene as the physics body's rectangle:

SKNode *edge = [SKNode node];
edge.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
[self addChild:edge];

Change the touchesBegan method to create a random ball when a touch event occurs. The 3 ball types should each have their own mass and restitution properties so that they bounce and affect each other in different ways:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
int random = arc4random_uniform(3);
SKSpriteNode *ball;
switch (random) {
case 0:
ball = [SKSpriteNode spriteNodeWithImageNamed:@"8Ball"];
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.size.width * 0.5];
ball.physicsBody.mass = 0.8;
ball.physicsBody.restitution = 0.2;
break;
case 1:
ball = [SKSpriteNode spriteNodeWithImageNamed:@"BeachBall"];
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.size.width * 0.5];
ball.physicsBody.mass = 0.1;
ball.physicsBody.restitution = 0.8;
break;
default:
ball = [SKSpriteNode spriteNodeWithImageNamed:@"SoccerBall"];
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.size.width * 0.5];
ball.physicsBody.mass = 0.4;
ball.physicsBody.restitution = 0.5;
break;
}
ball.position = location;
[self addChild:ball];
}
}
Challenge: Ball Challenge: Solution Part 2
08:56

Challenge: Ball Challenge: Solution

In this video we go through the solution to the ball challenge and have a bit of a play around with the properties of our physics bodies.

Code

Create a new Sprite Kit template project, add the 3 ball graphics to the project, and remove the code that generates the Hello World text and the code that creates a rotating spaceship node.

In the init method, change the background color to white:

self.backgroundColor = [SKColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];

In the init method, set up an invisible wall around the edge of the screen so that when we add some balls to the scene they will bounce around. Do this by creating an instance of SKNode that has an edge based physics body using the frame of the scene as the physics body's rectangle:

SKNode *edge = [SKNode node];
edge.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
[self addChild:edge];

Change the touchesBegan method to create a random ball when a touch event occurs. The 3 ball types should each have their own mass and restitution properties so that they bounce and affect each other in different ways:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
int random = arc4random_uniform(3);
SKSpriteNode *ball;
switch (random) {
case 0:
ball = [SKSpriteNode spriteNodeWithImageNamed:@"8Ball"];
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.size.width * 0.5];
ball.physicsBody.mass = 0.8;
ball.physicsBody.restitution = 0.2;
break;
case 1:
ball = [SKSpriteNode spriteNodeWithImageNamed:@"BeachBall"];
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.size.width * 0.5];
ball.physicsBody.mass = 0.1;
ball.physicsBody.restitution = 0.8;
break;
default:
ball = [SKSpriteNode spriteNodeWithImageNamed:@"SoccerBall"];
ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:ball.size.width * 0.5];
ball.physicsBody.mass = 0.4;
ball.physicsBody.restitution = 0.5;
break;
}
ball.position = location;
[self addChild:ball];
}
}
Challenge: Ball Challenge: Solution Part 3
05:42
+
Adding Halos to our Space Cannon Game
3 Lectures 16:57

Adding Randomness

Most games will involve some sort of random element. For this game, we want to spawn enemy halos at random positions. In this video we create a convenience method that will give us a random float value within a specified range.

Code

static inline CGFloat randomInRange(CGFloat low, CGFloat high)
{
CGFloat value = arc4random_uniform(UINT32_MAX) / (CGFloat)UINT32_MAX;
return value * (high - low) + low;
}

Links

Nice little FAQ on randomization functions: NSHipster: rand(3) / random(3) / arc4random(3) / et al.

Adding randomness
02:45

Something To Shoot

Our cannon is pointless if we don't have anything to shoot at. It's time to fix that up. In this video we'll setup a new method to create halo nodes that will randomly float down from the top of the screen. We'll use an action sequence to periodically call this method to give us some enemies to target.

Code

We add some constants for the angle and speed values we're going to use when setting a halo's velocity:

static const CGFloat kCCHaloLowAngle = 200.0 * M_PI / 180.0;
static const CGFloat kCCHaloHighAngle = 340.0 * M_PI / 180.0;
static const CGFloat kCCHaloSpeed = 100.0;

We add a new method that will add a new halo node at a random position above the top of the screen and give it a random downward velocity:

-(void)spawnHalo
{
// Create halo node.
SKSpriteNode *halo = [SKSpriteNode spriteNodeWithImageNamed:@"Halo"];
halo.position = CGPointMake(randomInRange(halo.size.width * 0.5, self.size.width - (halo.size.width * 0.5)),
self.size.height + (halo.size.height * 0.5));
halo.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:16.0];
CGVector direction = radiansToVector(randomInRange(kCCHaloLowAngle, kCCHaloHighAngle));
halo.physicsBody.velocity = CGVectorMake(direction.dx * kCCHaloSpeed, direction.dy * kCCHaloSpeed);
halo.physicsBody.restitution = 1.0;
halo.physicsBody.linearDamping = 0.0;
halo.physicsBody.friction = 0.0;
[_mainLayer addChild:halo];
}

We setup a new action sequence that we run against the scene to periodically spawn a new halo. Note: in the video I say that the duration will be modified by up to plus or minus the range, but it actually will only alter the duration by up to half the range. So that would give us a wait time of 1.5 - 2.5 seconds.

// Create spawn halo actions.

SKAction *spawnHalo = [SKAction sequence:@[[SKAction waitForDuration:2 withRange:1],
[SKAction performSelector:@selector(spawnHalo) onTarget:self]]];
[self runAction:[SKAction repeatActionForever:spawnHalo]];

Links

More detailed info on actions: Sprite Kit Programming Guide: Adding Actions to Nodes

Adding Halos
08:02

Review - Random in Range and Spawn Halo Action

This is a review video of the code we've implemented to spawn our halos. We take a closer look at the RandomInRange method and the actions we created to periodically spawn halos. Feel free to skip this video if you feel you have a pretty solid understanding of what's going on.

Review - Random in Range and Spawn Halo Action
06:10
+
Detecting Collisions and Contacts
4 Lectures 24:40

Bitfield

In this video we discuss bitfields. In order to detect contacts between nodes and to control how nodes react to collisions with other nodes we need to use bit masks. We go over the theory of how they work so we can start using them up in our projects.

Links

Wikipedia: Bit Field

BitFields
06:38

Space Cannon - Setting CollisionBitMask

Code

We declare 3 bitmasks:

static const uint32_t kCCHaloCategory = 0x1 << 0;
static const uint32_t kCCBallCategory = 0x1 << 1;
static const uint32_t kCCEdgeCategory = 0x1 << 2;

And set the categoryBitMask property on our various physics bodies:

leftEdge.physicsBody.categoryBitMask = kCCEdgeCategory;
rightEdge.physicsBody.categoryBitMask = kCCEdgeCategory;
ball.physicsBody.categoryBitMask = kCCBallCategory;
halo.physicsBody.categoryBitMask = kCCHaloCategory;

By setting the collisionBitMask property on the ball and halo physics bodies, we can control how they react when they collide with other physics bodies:

ball.physicsBody.collisionBitMask = kCCEdgeCategory;
halo.physicsBody.collisionBitMask = kCCEdgeCategory;

Links

Sprite Kit Programming Guide: Working with collisions and contacts

Collision BitMasks
05:45

Space Cannon - Receiving Collision Notifications

Code

We need to take a few steps in order to react to a collision between a ball and a halo. First we set the contactTestBitMask on the halo's physics body:

halo.physicsBody.contactTestBitMask = kCCBallCategory;

Next, in the header file for our scene we declare that we are implementing the SKPhysicsContactDelegate protocol:

@interface CCMyScene : SKScene <SKPhysicsContactDelegate>

We then tell the physics world that our scene object should be the delegate to receive contact notifications:

self.physicsWorld.contactDelegate = self;

And finally we implement the didBeginContact method:

-(void)didBeginContact:(SKPhysicsContact *)contact
{
SKPhysicsBody *firstBody;
SKPhysicsBody *secondBody;
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) {
firstBody = contact.bodyA;
secondBody = contact.bodyB;
} else {
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
if (firstBody.categoryBitMask == kCCHaloCategory && secondBody.categoryBitMask == kCCBallCategory) {
// Collision between halo and ball.
[firstBody.node removeFromParent];
[secondBody.node removeFromParent];
}
}

Links

Sprite Kit Programming Guide: Working with collisions and contacts

Contact Test BitMask
05:31

Review: Contact Delegate, Bit Masks

This is a review video of the steps we needed to take to get our didBeginContact method setup so that we could respond to two physics bodies coming into contact with one another. Feel free to skip this video if you feel you've already got a good grasp of how we got this stuff working.

Review: Contact Delegate, Bit Masks
06:46
+
Particle Effects and Explosions
4 Lectures 24:25

Space Cannon - Configuring Particle Effects

Particle Emitter Editor

In this video we take a look at the particle emitter editor and see how we can use it to design various particle effects to include in our games.

Links

Apples documentation explains in more detail the effects of the vairious properites of a particle emitter: Particle Emitter Editor Guide

Particles
07:06

Space Cannon - Adding An Explosion Effect

Code

We create a method to easily generate a new explosion node for us:

-(void)addExplosion:(CGPoint)position
{
NSString *explosionPath = [[NSBundle mainBundle] pathForResource:@"HaloExplosion" ofType:@"sks"];
SKEmitterNode *explosion = [NSKeyedUnarchiver unarchiveObjectWithFile:explosionPath];
explosion.position = position;
[_mainLayer addChild:explosion];
SKAction *removeExplosion = [SKAction sequence:@[[SKAction waitForDuration:1.5],
[SKAction removeFromParent]]];
[explosion runAction:removeExplosion];
}

We then call the method when we detect a collision between a ball and a halo:

[self addExplosion:firstBody.node.position];

Links

Sprite Kit Programming Guide: Emitter Nodes Create Particle Effects

Add Explosion Effect
04:34

Creating SKEmitterNodes Manually

We've seen how we can use the particle emitter editor built into Xcode to visually generate particle effects. It is also possible to manually code up a particle emitter. This video demonstrates how we create an instance of an SKEmitterNode using just code.

Code
SKEmitterNode *explosion = [SKEmitterNode node];
explosion.particleTexture = [SKTexture textureWithImageNamed:@"spark"];
explosion.particleLifetime = 1;
explosion.particleBirthRate = 2000;
explosion.numParticlesToEmit = 100;
explosion.emissionAngleRange = 360;
explosion.particleScale = 0.2;
explosion.particleScaleSpeed = - 0.2;
explosion.particleSpeed = 200;
Links

* SKEmitterNode Class Reference

Creating SKEmitterNodes Manually
05:45

Space Cannon - Shot Limiting

Our game would be too easy if we allowed the player to infintely shoot as often as they like. In this video we impose an available ammo limit of 5 that increases by 1 each second.

Code

We add a new property to he header file of our scene:

@property (nonatomic) int ammo;

In the init method, we add a sprite node to display how much ammo is available and create an action to increment the ammo each second:

// Setup Ammo.
_ammoDisplay = [SKSpriteNode spriteNodeWithImageNamed:@"Ammo5"];
_ammoDisplay.anchorPoint = CGPointMake(0.5, 0.0);
_ammoDisplay.position = _cannon.position;
[_mainLayer addChild:_ammoDisplay];
self.ammo = 5;
SKAction *incrementAmmo = [SKAction sequence:@[[SKAction waitForDuration:1],
[SKAction runBlock:^{
self.ammo++;
}]]];
[self runAction:[SKAction repeatActionForever:incrementAmmo]];

Overriding the ammo property's setter allows us to easily impose our limit and update the ammo display at the same time:

-(void)setAmmo:(int)ammo
{
if (ammo >= 0 && ammo <= 5) {
_ammo = ammo;
_ammoDisplay.texture = [SKTexture textureWithImageNamed:[NSString stringWithFormat:@"Ammo%%d", ammo]];
}
}

In our shoot method, we limit our shots and decrement the ammo with a simple if statement:

if (self.ammo > 0) {
self.ammo--;
...
}
Shot Limiting
07:00
+
Challenge 2: Alternate Shot Limiting
2 Lectures 06:00
Challenge: Alternate Shot Limiting

In the video where we added shot limiting, I talked about the idea that we could instead limit our shots, by only allowing a couple of cannon balls on screen at any one time. See if you can work out how to implement this behavior and make it so that only 2 cannon balls can be on screen at the same time.

Challenge: Alternate Shot Limiting
00:57

Challenge: Alternate Shot Limiting: Solution

There are a couple of ways we could solve our shot limiting challenge. One way would be to take advantage of our existing ammo property but set it's maximum to 2. We would then need to remove our action that automatically increases our ammo over time and instead increase the ammo each time a cannon ball is removed from our scene. This happens in two places; when a ball collides with a halo, and when a ball moves outside of the screen.

A second way that we could solve the challenge would be to check how many cannon ball nodes are in the scene when we try to shoot. If there are 2 or more, then we don't allow the player to shoot. We could set this up in the shoot method:

Code
-(void)shoot
{
int availableAmmo = 2;
for (SKNode *node in _mainLayer.children) {
if([node.name isEqualToString:@"ball"])
{
availableAmmo--;
}
}
if (availableAmmo > 0) {
...
Challenge: Alternate Shot Limiting: Solution
05:03
+
Shields and start a Lifebar
3 Lectures 17:56
Space Cannon - Add Shields

Lets give the player a first line of defense by adding a row of shields above their cannon. When a halo hits a shield it should destroy both the shield and he halo.

Code

We delcare a new category for our shields:

static const uint32_t kCCShieldCategory = 0x1 << 3;

In our init method we add some code to setup 6 shields above the cannon:

// Setup shields
for (int i = 0; i < 6; i++) {
SKSpriteNode *shield = [SKSpriteNode spriteNodeWithImageNamed:@"Block"];
shield.position = CGPointMake(35 + (50 *i), 90);
[_mainLayer addChild:shield];
shield.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(42, 9)];
shield.physicsBody.categoryBitMask = kCCShieldCategory;
shield.physicsBody.collisionBitMask = 0;
}

We update the contactTestBitMask property of our halos to include the new shield category:

halo.physicsBody.contactTestBitMask = kCCBallCategory | kCCShieldCategory;

Finally we respond to a contact between a halo and shield in the didBeginContact method:

if (firstBody.categoryBitMask == kCCHaloCategory && secondBody.categoryBitMask == kCCShieldCategory) {
// Collision between halo and shield.
[self addExplosion:firstBody.node.position];
[firstBody.node removeFromParent];
[secondBody.node removeFromParent];
}
Add Shields
05:53

Review - Add Shields

We added quite a bit of code to create our shields. In this video we review all this code in closer detail. If you feel you've got a good understanding on how it all works, then you may want to skip this video.

Review - Add Shields
05:51

Space Cannon - Add Life Bar

In this video we'll create a game over condition by adding a bar above the cannon that if hit by a halo triggers the end of the game.

Code

First we need a new category for the life bar:

static const uint32_t kCCLifeBarCategory = 0x1 << 4;

We create the life bar node in the init method:

SKSpriteNode *lifeBar = [SKSpriteNode spriteNodeWithImageNamed:@"BlueBar"];
lifeBar.position = CGPointMake(self.size.width * 0.5, 70);
lifeBar.physicsBody = [SKPhysicsBody bodyWithEdgeFromPoint:CGPointMake(-lifeBar.size.width * 0.5, 0) toPoint:CGPointMake(lifeBar.size.width * 0.5, 0)];
lifeBar.physicsBody.categoryBitMask = kCCLifeBarCategory;
[_mainLayer addChild:lifeBar];

We update the contactTestBitMask property of the halos to include the new life bar category:

halo.physicsBody.contactTestBitMask = kCCBallCategory | kCCShieldCategory |kCCLifeBarCategory;

We refactor our addExplosion method to take the name of the explosion we wish to add:

-(void)addExplosion:(CGPoint)position withName:(NSString*)name
{
NSString *explosionPath = [[NSBundle mainBundle] pathForResource:name ofType:@"sks"];
SKEmitterNode *explosion = [NSKeyedUnarchiver unarchiveObjectWithFile:explosionPath];
...
}

We can then update our didBeginContactMethod to respond to the halo/life bar contact:

if (firstBody.categoryBitMask == kCCHaloCategory && secondBody.categoryBitMask == kCCLifeBarCategory) {
// Collision between halo and life bar.
[self addExplosion:firstBody.node.position withName:@"HaloExplosion"];
[self addExplosion:secondBody.node.position withName:@"LifeBarExplosion"];
[firstBody.node removeFromParent];
[secondBody.node removeFromParent];
Add Life Bar
06:12
+
Challenge 3: Explosion on Bounce
2 Lectures 06:43
Challenge: Add Explosion on Bounce

See if you can create a new type of mini explosion that occurs every time a cannon ball bounces off the side of the screen. You will need to setup a new particle effect file and detect when there is a collision between a cannon ball and an edge. In terms of positioning your explosion, check out the contactPoint property that is part of the SKPhysicsContact object in the didBeginContact method to help get your explosion right next to the edge.

Challenge: Add Explosion on Bounce
00:27

Challenge: Add Explosion on Bounce: Solution

In this video we run through how we can solve the challenge to display an explosion effect each time a cannon ball bounces off the edge of the screen.

Code

You'll first need to create a new particle effect file with the explosion effect you want for the cannon ball bounce.

We need to detect when there is contact between a ball node and an edge. We set this up by setting the contactTestBitMask property of our ball's physics body:

ball.physicsBody.contactTestBitMask = kCCEdgeCategory;

We can then add a new if statement in the didBeginContact method to respond to the contact between ball and edge. We can use the contactPoint property of the contact object that's passed into the didBeginContact method to position our explosion:

if (firstBody.categoryBitMask == kCCBallCategory && secondBody.categoryBitMask == kCCEdgeCategory) {
[self addExplosion:contact.contactPoint withName:@"BounceExplosion"];
}
Challenge: Add Explosion on Bounce Solution
06:16
52 More Sections
About the Instructor
Eliot Arntz
4.5 Average rating
147 Reviews
16,145 Students
2 Courses
iOS Developer and Teacher

Eliot regularly teaches iOS development classes and workshops at General Assembly and guest lectures for companies and development boot camps around NYC. He also taught the inaugural class for Coalition for Queens which focused on increasing diversity in iOS development. He also coaches students in a one-on-one environment with a focus on transitioning to full time development. Eliot cofounded and organizes the iOS Office Hours meetup NYC.

In his free time he works as a contractor for startups focusing on agile development.

Find me on twitter @EliotArntz - I check my direct messages quite frequently.

Mr. John Omar
4.5 Average rating
247 Reviews
16,705 Students
7 Courses
Designer, developer, teacher at Bitfountain

John was the lead iOS developer at Fast Society and Cameo until he started Bitfountain in 2012. The apps that John has contributed to have appeared in TechCrunch, Mashable and the New York Times. At Bitfountain, John oversees all projects from a technical and strategic perspective. At Bitfountain, John has taught over 120,000 students how to code online.

Jed Hastwell
4.7 Average rating
76 Reviews
5,224 Students
1 Course
iOS Games Developer and Teacher

Jed worked for many years as a web developer for various companies in Australia and the UK. He co-founded indie games development studio, Whistlefire that recently launched their first game for iOS, Jungle Raider. He currently resides in Berlin where he is working for Toywheel, designing and building mobile games and digital toys for kids.