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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
SpriteKit Animations and Texture Atlases in Swift
20 mins
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.
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:
- You declare
multiplierDirection
, aCGFloat
variable you'll use to set the bear's direction, just as you did earlier intouchesEnded()
. - 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. - 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.
- You calculate how long it should take the bear to move along this length, by dividing the length by the desired speed.
- 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:)
:
- Start the legs moving on your bear if he is not already moving his legs.
- Create a move action specifying where to move and how long it should take.
- Create a done action that will run a block to stop the animation.
- 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.