How to Make a Game Like Mega Jump With Sprite Kit: Part 1/2

In this two-part tutorial series, you’ll learn how to create a game like Mega Jump using the latest and greatest game framework for iOS: Sprite Kit. By Toby Stephens.

Leave a rating/review
Save for later
Share
You are currently viewing page 2 of 4 of this article. Click here to view the first page.

Adding the Player Node

It’s time for your Uber Jumper to enter the scene. In MyScene.m, add the following method:

- (SKNode *) createPlayer
{
  SKNode *playerNode = [SKNode node];
  [playerNode setPosition:CGPointMake(160.0f, 80.0f)];

  SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:@"Player"];
  [playerNode addChild:sprite];

  return playerNode;
}

As with the background node you added earlier, you create a new SKNode and add the SKSpriteNode to it as a child. You position the player node so that it is not at the bottom of the scene.

To add the player node to the scene, you first need to create a foreground node. As discussed above, the foreground node will contain the player, the stars and the platforms. That means when you move the foreground node, all the game elements it contains will move together.

Add the following to initWithSize:, just after the line that adds _backgroundNode to the scene:

// Foreground
_foregroundNode = [SKNode node];
[self addChild:_foregroundNode];

Now that you have your foreground node for the gameplay elements, you can add the player node to it.

At the top of MyScene.m, add the following variable to the class extension along with the other variables you added to hold the layer nodes:

// Player
SKNode *_player;

Now add the player node to the scene by inserting the following into initWithSize:, just after the line that adds _foreground to the scene:

// Add the player
_player = [self createPlayer];
[_foregroundNode addChild:_player];

Build and run to see your Uber Jumper ready to start their adventure:

06-ForegroundNode

Adding Gravity and a Physics Body

The Uber Jumper looks a little too comfortable sitting there, so you're going bring some physics into play and see what happens.

First, your game can’t have physics without gravitation. In MyScene.m, add the following line to initWithSize:, after the line that sets the background color:

// Add some gravity
self.physicsWorld.gravity = CGVectorMake(0.0f, -2.0f);

You add a suitable amount of gravity to the physics world, based on the gameplay you want to achieve. Gravity has no influence along the x-axis, but produces a downward force along the y-axis.

Build and run to see how this gravity affects the player node.

06-ForegroundNode

Hmm… Nothing happened. Why isn’t the gravity affecting the player node? See if you can figure it out yourself before clicking below to see the answer.

[spoiler title="Solution"]The force produced by the gravity in the physics world only affects dynamic physics bodies in the scene, but SKNodes like your player node do not have physics bodies defined by default. You need to define a physics body for your player node.[/spoiler]

In createPlayer, add the following just before the return statement at the end:

// 1
playerNode.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:sprite.size.width/2];
// 2
playerNode.physicsBody.dynamic = YES;
// 3
playerNode.physicsBody.allowsRotation = NO;
// 4
playerNode.physicsBody.restitution = 1.0f;
playerNode.physicsBody.friction = 0.0f;
playerNode.physicsBody.angularDamping = 0.0f;
playerNode.physicsBody.linearDamping = 0.0f;

The above code defines the player node’s physics body. Take a look at it in detail:

  1. Each physics body needs a shape that the physics engine can use to test for collisions. The most efficient body shape to use in collision detection is a circle (easier to detect if overlaps another circle you see), and fortunately a circle fits your player node very well. The radius of the circle is half the width of the sprite.
  2. Physics bodies can be static or dynamic. Dynamic bodies are influenced by the physics engine and are thus affected by forces and impulses. Static bodies are not, but you can still use them in collision detection. That is, a static body will never move, but things can bump into it. Since you want your player node to be affected by gravity, you set it’s dynamic property to YES.
  3. You want your player node to remain upright at all times and so you disable rotation of the node.
  4. Since you're handling collisions yourself in this game, you adjust the settings on the player node's physics body so that it has no friction or damping. However, you set its restitution to 1, which means the physics body will not lose any of its momentum during collisions.

Build and run to see your player sprite fall off the bottom of the screen as gravity draws it relentlessly toward the Earth’s core.

05-BackgroundNode

Perhaps that sounded a little melodramatic, but how is an Uber Jumper supposed to get anywhere in this world?

Tap To Start

Now that gravity is working, you’re going to give the player sprite a fighting chance and make its physics body static until the user actually decides to start playing.

Still inside MyScene.m, find the line in createPlayer that sets the dynamic property on playerNode's physics body. Change it to NO, as shown here:

playerNode.physicsBody.dynamic = NO;

You are going to write code to allow the player to start the game by tapping the screen. The player needs to know this, though, so first you need to put some instructions on the screen.

Since the instructions will go in your HUD node, create that layer first. In initWithSize:, just after where you add the foreground node to the scene, insert the following code:

// HUD
_hudNode = [SKNode node];
[self addChild:_hudNode];

The starter project includes an image that tells the player to tap to start the game, so add the following variable to the class extension at the top of MyScene.m:

// Tap To Start node
SKSpriteNode *_tapToStartNode;

To show the node, add the following code to initWithSize:, just after the line that adds the player node:

// Tap to Start
_tapToStartNode = [SKSpriteNode spriteNodeWithImageNamed:@"TapToStart"];
_tapToStartNode.position = CGPointMake(160, 180.0f);
[_hudNode addChild:_tapToStartNode];

Build and run, and you will see the instruction to “Tap to Start” above the player sprite:

07-TapToStart

To respond to touch events and start the game, add the following method to MyScene.m:

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
  // 1
  // If we're already playing, ignore touches
  if (_player.physicsBody.dynamic) return;

  // 2
  // Remove the Tap to Start node
  [_tapToStartNode removeFromParent];

  // 3
  // Start the player by putting them into the physics simulation
  _player.physicsBody.dynamic = YES;
  // 4
  [_player.physicsBody applyImpulse:CGVectorMake(0.0f, 20.0f)];
}

Take a look at the method in detail:

  1. You check to see if the player node is already dynamic. If so, you ignore the touch event and return.
  2. You remove the Tap to Start node.
  3. You change the player node’s physics body to dynamic so that the physics engine can influence it.
  4. You give the player node an initial upward impulse to get them started.

Build and run. When you tap the screen, the game removes the Tap to Start node and thrusts the player sprite upward, albeit briefly, before gravity takes over.

Toby Stephens

Contributors

Toby Stephens

Author

Over 300 content creators. Join our team.