Centering the camera on a sprite
Games often require the camera to follow the player sprite as it moves through space. We definitely want this camera behavior for Pierre, our penguin character, whom we will soon be adding to the game. With iOS9, Apple added a new SKCameraNode
class, which makes this task easy. We will attach an SKCameraNode
to our scene and position it directly over the player to keep their character centered in the view.
You can find the code for our camera functionality in the following code block. Read the comments for a detailed explanation. This is a quick recap of the changes:
- Our
didMove
function was becoming too crowded. We broke out our flying bee code into a new function namedaddTheFlyingBee
. Later, we will encapsulate game objects, such as bees, into their own classes. - We created two new constants on the
GameScene
class: the camera node and the bee node. - We updated the
didMove
function. It assigns the new camera node to the scene's camera. - We have added a new function to add a background sprite, just to show that the bee is actually moving and that the camera is centered on the bee.
- Inside the new
addTheFlyingBee
function, we removed the bee constant, asGameScene
now declares it above as its own property. - We are implementing a new function:
didSimulatePhysics
. SpriteKit calls this function every frame after performing physics calculations and adjusting positions. It's a great place to update our camera position. The code to change the camera position and keep the view centered on the player resides in this new function.
Please update your entire GameScene.swift
file to match mine:
import SpriteKit classGameScene: SKScene { // Create a constant cam as a SKCameraNode: let cam = SKCameraNode() // Create our bee node as a property of GameScene so we can // access it throughout the class // (Make sure to remove the old bee declaration below) let bee = SKSpriteNode() override func didMove(to view: SKView) { self.anchorPoint = .zero self.backgroundColor = UIColor(red: 0.4, green: 0.6, blue: 0.95, alpha: 1.0) // Assign the camera to the scene self.camera = cam // Call the new bee function self.addTheFlyingBee() // Add background self.addBackground() } // A new function Override func didSimulatePhysics() { // Keep the camera centered on the bee // Notice the !operator after camera. SKScene's camera // is an optional, but we know it is there since we // assigned it above in the didMove function. We can tell // Swift that we know it can unwrap this value by using // the !operator after the property name. self.camera!.position = bee.position } // new function to add background func addBackground(){ let bg = SKSpriteNode(imageNamed:"background-menu") bg.position = CGPoint(x: 250, y: 250) self.addChild(bg) } // I moved all of our bee animation code into a new function: func addTheFlyingBee() { // Position our bee bee.position = CGPoint(x: 250, y: 250) bee.size = CGSize(width: 28, height: 24) // Add the bee to the scene self.addChild(bee) // Find the bee textures from the texture atlas let beeAtlas = SKTextureAtlas(named:"Enemies") let beeFrames:[SKTexture] = [ beeAtlas.textureNamed("bee"), beeAtlas.textureNamed("bee-fly")] // Create a new SKAction to animate between the frames let flyAction = SKAction.animate(with: beeFrames, timePerFrame: 0.14) // Create an SKAction to run the flyAction repeatedly let beeAction = SKAction.repeatForever(flyAction) // Instruct our bee to run the final repeat action: bee.run(beeAction) // Set up new actions to move our bee back and forth: let pathLeft = SKAction.moveBy(x: -200, y: -10, duration: 2) let pathRight = SKAction.moveBy(x: 200, y: 10, duration: 2) let flipTextureNegative = SKAction.scaleX(to: -1, duration: 0) let flipTexturePositive = SKAction.scaleX(to: 1, duration: 0) // Combine actions into a cohesive flight sequence let flightOfTheBee = SKAction.sequence([ pathLeft,flipTextureNegative, pathRight, flipTexturePositive]) // Last, create a looping action that will repeat forever let neverEndingFlight = SKAction.repeatForever(flightOfTheBee) // Tell our bee to run the flight path, and away it goes! bee.run(neverEndingFlight) } }
Run the game. You should see our bee stuck directly at the center of the screen, flipping back and forth every two seconds:
The bee is actually changing position, just as before, but the camera is moving to keep the bee centered on the screen. When we add more game objects in Chapter 3, Mixing in the Physics, our bee will appear to be flying as the entire world pans past the screen.
Note
Checkpoint 2-B
The code up to this point is available in this chapter's code resources.