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

In part one of this two-part tutorial series, you’ll start creating a game like Mega Jump, and implement the overall scene, physics, and sound effects using Swift and Sprite Kit! By Michael Briscoe.

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 GameScene.swift, add the following method:

func createPlayer() -> SKNode {
  let playerNode = SKNode()
  playerNode.position = CGPoint(x: self.size.width / 2, y: 80.0)
        
  let sprite = SKSpriteNode(imageNamed: "Player")
  playerNode.addChild(sprite)
        
  return playerNode
}

As with the background node you added earlier, you create a new SKNode and add the SKSpriteNode containing the player sprite to it as a child. You position the player node so that it is horizontally centered and just above 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 init(size:), just after the line that adds backgroundNode to the scene:

// Foreground
foregroundNode = SKNode()
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 GameScene.swift, add the following property along with the others you added to hold the layer nodes:

// Player
var player: SKNode!

Now add the player node to the scene by inserting the following into init(size:), just after the line that adds foregroundNode to the scene:

// Add the player
player = createPlayer()
foregroundNode.addChild(player)

Build and run to see your Uber Jumper ready to start a new 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 GameScene.swift, add the following line to init(size:), after the line that sets the background color:

// Add some gravity
physicsWorld.gravity = CGVector(dx: 0.0, dy: -2.0)

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 SKNode objects 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(circleOfRadius: sprite.size.width / 2)
// 2
playerNode.physicsBody?.dynamic = true
// 3
playerNode.physicsBody?.allowsRotation = false
// 4
playerNode.physicsBody?.restitution = 1.0
playerNode.physicsBody?.friction = 0.0
playerNode.physicsBody?.angularDamping = 0.0
playerNode.physicsBody?.linearDamping = 0.0

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. A static body such as a wall or a solid platform will never move, but things can bump into it. Since you want your player node to be affected by gravity, you set its dynamic property to true.
  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 GameScene.swift, find the line in createPlayer that sets the dynamic property on playerNode‘s physics body. Change it to false, as shown here:

playerNode.physicsBody?.dynamic = false

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 init(size:), just after where you add the foreground node to the scene, insert the following code:

// HUD
hudNode = SKNode()
addChild(hudNode)

The graphic resources include an image that tells the player to tap to start the game, so add the following variable to the properties at the top of GameScene.swift:

// Tap To Start node
let tapToStartNode = SKSpriteNode(imageNamed: "TapToStart")

To show the node, add the following code to init(size:), just after the line that adds the player node:

// Tap to Start
tapToStartNode.position = CGPoint(x: self.size.width / 2, y: 180.0)
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 GameScene.swift:

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
  // 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 = true
        
  // 4
  player.physicsBody?.applyImpulse(CGVector(dx: 0.0, dy: 20.0))
}

Take a look at the method in detail:

  1. Check to see if the player node is already dynamic. If so, you ignore the touch event and return.
  2. Remove the Tap to Start node.
  3. Change the player node’s physics body to dynamic so that the physics engine can influence it.
  4. 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.

Michael Briscoe

Contributors

Michael Briscoe

Author

Over 300 content creators. Join our team.