How to Make a Line Drawing Game with Sprite Kit and Swift

Learn how to make a Line Drawing Game like Flight Control with Sprite Kit and Swift! By Jean-Pierre Distler.

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

Continuous Movement

Actually, the pig stops moving after it reaches the last waypoint. For Hogville, it makes more sense and will be more challenging if the pigs keep moving. Otherwise, you could simply draw a path to the pigs straight to their pens and the game would be over!

Let's correct this. Open Pig.swift and add the following code at the end of move():

else {
  newPosition = CGPoint(x: currentPosition.x + velocity.x * CGFloat(dt),
                                   y: currentPosition.y + velocity.y * CGFloat(dt))
  position = newPosition
}

This code simply continues to move the pig with its most recently calculated velocity when it runs out of waypoints. Remember, velocity includes both direction and speed. The last step is to move the line
position = newPosition outside the if/else-statement and at the end of move.

Build and run, and watch your pig moving and moving and moving... until you can’t see it anymore. This little piggy went off screen!

Moving_Offscreen

What you need is a method to check if the pig is about to leave the screen and if so, switch its direction.

Also in Pig.swift, add this method:

func checkBoundaries(position: CGPoint) -> CGPoint {
  //1
  var newVelocity = velocity
  var newPosition = position
 
  //2      
  let bottomLeft = CGPoint(x: 0, y: 0)
  let topRight = CGPoint(x:scene!.size.width, y:scene!.size.height)
 
  //3
  if newPosition.x <= bottomLeft.x {
    newPosition.x = bottomLeft.x
    newVelocity.x = -newVelocity.x
  } else if newPosition.x >= topRight.x {
    newPosition.x = topRight.x
    newVelocity.x = -newVelocity.x
  }
 
  if newPosition.y <= bottomLeft.y {
    newPosition.y = bottomLeft.y
    newVelocity.y = -newVelocity.y
  } else if newPosition.y >= topRight.y {
    newPosition.y = topRight.y
    newVelocity.y = -newVelocity.y
  }
 
  velocity = newVelocity
 
  return newPosition
}

This looks more complicated than it is, so let’s look more closely:

  1. First, you assign the current velocity and point to local variables.
  2. Here you define the important points on the screen. You can use bottomLeft to check if the pig is moving off screen from the left or bottom sides and topRight to check the top and right sides of the screen. You perform these checks inside the following if statements, one for each side of the screen.
  3. The first if statement checks the x value of newPosition. If this value is zero or less, the pig is leaving the screen from the left side. To avoid this, you set the pig's x-position to the left boundary—zero—and reverse the x-component of the velocity so the pig starts moving in the opposite direction. The other if statements do the same for the remaining three bounds of the screen.
  4. At the end, you change velocity to whatever value you calculated and then return newPosition.

To make use of this new method, change the last line in move() from this:

position = newPosition

To this:

position = checkBoundaries(newPosition)

Build and run your project again and watch the pig bounce off of the screen’s borders. You’ve got yourself a pig pen!

Bouncing_Pig

Rotating the Sprite

Before adding the actual gameplay, there are some minor improvements you should make. First, the pig doesn't rotate at all, which looks a bit weird. Like most animals, pigs normally walk facing forward rather than backward or to the side!

Rotate the pig so that it faces the direction it’s moving by adding the following line to the end of move() in Pig.swift:

zRotation = atan2(CGFloat(velocity.y), CGFloat(velocity.x)) + CGFloat(M_PI_2)

atan2 returns the angle between the x-axis and the given point. You add M_PI_2 because the pig image you use faces down and the value you receive from atan2 assumes the image faces to the right. Therefore, by adding M_PI_2, you rotate the pig by 90° counterclockwise.

A rotating pig

Note: If this is too much math for you, check out our open source SKTUtils library. The library includes a ton of helper functions that abstracts common math like this; for example it extends CGPoint so you can just access an angle property to convert a vector to an angle.

Note: If this is too much math for you, check out our open source SKTUtils library. The library includes a ton of helper functions that abstracts common math like this; for example it extends CGPoint so you can just access an angle property to convert a vector to an angle.

Animating the Sprite

Now that the pig faces the direction it's moving, it's time to add a pretty animation. Add the following new property at the top of Pig.swift:

var moveAnimation: SKAction 

Next, go to init(imageNamed:) and add the following lines directly before you call super.init():

let textures = [SKTexture(imageNamed:"pig_1"), SKTexture(imageNamed:"pig_2"), SKTexture(imageNamed:"pig_3")]
moveAnimation = SKAction.animateWithTextures(textures, timePerFrame:0.1)

This creates three textures, each of which represents a frame of the animation. The last line creates an SKAction that animates the pig’s movement using the three textures and stores the action in moveAnimation. The game will show each frame for 0.1 seconds, resulting in a nice walking animation for the pig. now do the same in init(coder:)

The last step is to run the animation. Go to move() and add the following lines at the beginning of the method:

if(actionForKey("moveAction") == nil) {
  runAction(moveAnimation, withKey:"moveAction")
}

First, you check if an animation named "moveAction" is already running and add it if there is no such animation. This ensures that the game adds the animation only once. Without this check, you wouldn't see the animation because it would start from the beginning every time you called move.

Build and run, and watch your pig animate around the screen as you direct it.

Move_Animation1

Your Gameplay Strategy

Let’s pause to think about how the gameplay will work and what you need to achieve it.

The basic idea behind Hogville is that pigs will appear at random positions on the left side of the screen and from there, move in random directions. The time between the appearances of each new pig will decrease until it reaches a threshold defined by you.

The player must herd all of these pigs to a trough of food where they can eat and after that, bring them to a barn where they can sleep. If any two pigs collide, the game is over.

Here are the needed steps:

  1. Add sprites for the food trough and barn.
  2. Spawn pigs over time.
  3. Add collision handling.
  4. Add logic that controls when a pig needs food or is ready to sleep.
  5. Handle win/lose conditions.

You will go step by step through this list to finish your game. Don't panic—this tutorial is here to guide you!