Centering the camera on a sprite
Games often require that the camera follows 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. Since SpriteKit does not come with built-in camera functionality, we will create our own structure to simulate the effect we want.
One way we could accomplish this is by keeping Pierre in one position and moving every other object past him. This is effective, yet semantically confusing, and can cause errors when you are positioning game objects.
Creating a new world
I prefer to create a world node and attach all of our game nodes to it (instead of directly to the scene). We can move Pierre forward through the world and simply reposition the world node so that Pierre is always at the center of our device's viewport. All of our enemies, power-ups, and structures will be children of the world node, and will appear to move past the screen as we scroll through the world.
Tip
Each sprite node's position is always relative to its direct parent. When you change a node's position, all of its child nodes come along for the ride. This is very handy behavior for simulating our camera.
This diagram illustrates a simplified version of this technique with some made-up numbers:
You can find the code for our camera functionality in the following code block. Read the comments for a detailed explanation. This is just a quick recap of the changes:
- Our
didMoveToView
function was becoming too crowded. I broke out our flying bee code into a new function namedaddTheFlyingBee
. Later, we will encapsulate game objects, such as bees, into their own classes. - I created two new constants on the
GameScene
class: the world node and the bee node. - I updated the
didMoveToView
function. It adds the world node to the scene's node tree, and calls the newaddTheFlyingBee
function. - Inside the new bee function, I removed the bee constant, as
GameScene
now declares it above as its own property. - Inside the new bee function, instead of adding the bee node to the scene, with
self.addChild(bee)
, we want to add it to the world, withworld.addChild(bee)
. - We are implementing a new function:
didSimulatePhysics
. SpriteKit calls this function every frame after performing physics calculations and adjusting positions. It is a great place to update our world position. The math to change the world position resides in this new function.
Please update your entire GameScene.swift
file to match mine:
import SpriteKit class GameScene: SKScene { // Create the world as a generic SKNode let world = SKNode() // 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 inside the // didMoveToView function.) let bee = SKSpriteNode() override func didMoveToView(view: SKView) { self.backgroundColor = UIColor(red: 0.4, green: 0.6, blue: 0.95, alpha: 1.0) // Add the world node as a child of the scene self.addChild(world) // Call the new bee function self.addTheFlyingBee() } // 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) // Notice we now attach our bee node to the world node: world.addChild(bee) /* all of the same bee animation code remains here, I am excluding it in this text for brevity */ } // A new function override func didSimulatePhysics() { // To find the correct position, subtract half of the // scene size from the bee's position, adjusted for any // world scaling. // Multiply by -1 and you have the adjustment to keep our // sprite centered: let worldXPos = -(bee.position.x * world.xScale - (self.size.width / 2)) let worldYPos = -(bee.position.y * world.yScale - (self.size.height / 2)) // Move the world so that the bee is centered in the scene world.position = CGPoint(x: worldXPos, y: worldYPos) } }
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 world is compensating to keep the bee centered on the screen. When we add more game objects in Chapter 3, Mix in the Physics, our bee will appear to fly as the entire world pans past the screen.