SpriteKit Animations and Texture Atlases in Swift

Create an animated walking bear while you learn about using texture atlases with animations in this SpriteKit tutorial! By Kevin Colligan.

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

Changing Animation Facing Direction

Still in GameScene.swift, add the following method to detect user touches:

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
  let touch = touches.first!
  let location = touch.location(in: self)
  
  var multiplierForDirection: CGFloat
  if location.x < frame.midX {
    // walk left
    multiplierForDirection = 1.0
  } else {
    // walk right
    multiplierForDirection = -1.0
  } 
  
  bear.xScale = abs(bear.xScale) * multiplierForDirection
  animateBear()
}

SpriteKit calls touchesEnded(_:with:) when the user's finger lifts off the screen at the end of a tap.

In the method, you determine which side of the screen was tapped — left or right of center. You want the bear to face in the direction of the tap. You do this by making the node's xScale positive when the bear should face left (the bear walks to the left by default), and negative to flip the image when the bear should face right.

Finally, you call animateBear() to restart the animation each time you tap the screen.

Build and run the project, and you'll see your bear happily strolling on the screen as usual. Tap on the left and right sides of the screen to get the bear to change directions.

Bears have a fine sense of direction

Moving the Bear Around the Screen

Right now, it looks like the bear is walking in-place on a treadmill. The next step is to get him to meander to different places on the screen.

First, remove the call to animateBear() at the end of didMove(to:). You want the bear to start moving when the user taps the screen, not automatically.

Next, add this helper method to the class:

func bearMoveEnded() {
  bear.removeAllActions()
}

This will remove all actions and stop the animation. You'll call this later when the bear reaches the edge of the screen.

Before taking your bear out for a walk, clean-up touchesEnded(_:with:) by moving all bear-related code to its own method. Replace the entire method with:

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
  let touch = touches.first!
  let location = touch.location(in: self)
  moveBear(location: location)
}

The code above records the touch location and sends it over to a new method, moveBear(location:). It also spawns a warning from Xcode because you haven't yet created this method. Add the following code right after animateBear():

func moveBear(location: CGPoint) {
  // 1
  var multiplierForDirection: CGFloat
  
  // 2
  let bearSpeed = frame.size.width / 3.0
  
  // 3
  let moveDifference = CGPoint(x: location.x - bear.position.x, y: location.y - bear.position.y)
  let distanceToMove = sqrt(moveDifference.x * moveDifference.x + moveDifference.y * moveDifference.y)
  
  // 4
  let moveDuration = distanceToMove / bearSpeed
  
  // 5
  if moveDifference.x < 0 {
    multiplierForDirection = 1.0
  } else {
    multiplierForDirection = -1.0
  }
  bear.xScale = abs(bear.xScale) * multiplierForDirection
}

Here's what's going on step-by-step:

  1. You declare multiplierDirection, a CGFloat variable you'll use to set the bear's direction, just as you did earlier in touchesEnded().
  2. You define the bearSpeed to be equal to the screen width divided by 3, so the bear will be able to travel the width of the scene in 3 seconds.
  3. You need to figure out how far the bear needs to move along both the x and y axes, by subtracting the bear's position from the touch location. You then calculate the distance the bear moves along a straight line (the hypotenuse of a triangle formed from the bear's current position and the tap point). For a full tutorial on the math of game programming, check out Trigonometry for Games.
  4. You calculate how long it should take the bear to move along this length, by dividing the length by the desired speed.
  5. Finally, you look to see if the bear is moving to the right or to the left by looking at the x axis of the move difference. If it's less than 0, he's moving to the left; otherwise, to the right. You use the same technique of creating a multiplier for the xScale to flip the sprite.

Now all that's left is to run the appropriate actions. That's another substantial chunk of code — add the following to the end of moveBear(location:):

// 1
if bear.action(forKey: "walkingInPlaceBear") == nil {
  // if legs are not moving, start them
  animateBear()
}

// 2
let moveAction = SKAction.move(to: location, duration:(TimeInterval(moveDuration)))

// 3
let doneAction = SKAction.run({ [weak self] in
  self?.bearMoveEnded()
})

// 4
let moveActionWithDone = SKAction.sequence([moveAction, doneAction])
bear.run(moveActionWithDone, withKey:"bearMoving")

Here's what's happening in this second half of moveBear(location:):

  1. Start the legs moving on your bear if he is not already moving his legs.
  2. Create a move action specifying where to move and how long it should take.
  3. Create a done action that will run a block to stop the animation.
  4. Combine these two actions into a sequence of actions, which means they will run in order sequentially — the first runs to completion, then the second runs. You have the bear sprite run this sequence with the key "bearMoving". As with the animation action, using a unique key here will ensure there is only one movement action running at a time.

Note: SpriteKit supports sequential and grouped actions. A sequential action means each specified action runs one after the other (sequentially). Sometimes you may want multiple actions to run at the same time. This can be accomplished by specifying a group action where all the actions specified run in parallel.

You also have the flexibility to set up a series of sequential actions that contain grouped actions and vice versa! For more details see the SKAction class in Apple's SpriteKit documentation.

Note: SpriteKit supports sequential and grouped actions. A sequential action means each specified action runs one after the other (sequentially). Sometimes you may want multiple actions to run at the same time. This can be accomplished by specifying a group action where all the actions specified run in parallel.

You also have the flexibility to set up a series of sequential actions that contain grouped actions and vice versa! For more details see the SKAction class in Apple's SpriteKit documentation.

That was a lot of code — but was it worth it? Build and run to see! Now you can tap the screen to move your bear around.

Your walking bear is now complete!

Kevin Colligan

Contributors

Kevin Colligan

Author

Kyle Gorlick

Tech Editor

Morten Faarkrog

Final Pass Editor

Richard Critz

Team Lead

Over 300 content creators. Join our team.