# Working with Cameras in SpriteKit Game

I’m currently working on a game that has a vertical tileMap and a character toward the bottom of the screen that can only be moved on the x-axis. I started making this game after working through the tutorial for DropCharge in the 2DiOS Games book. Currently to make it look like the game is scrolling I gave my character a velocity of dx:500 to have him travel up the tileMap.

When I run the simulator the camera starts towards the bottom left of everything and then looks like it is catching up to my scene contents. I believe this has to do with the code i implemented for my camera following my player.

``````override func didSimulatePhysics() {
cameraNode.position = CGPoint(x: player.parent!.position.x, y: player.parent!.position.y)
self.centerOnNode(node: cameraNode)
}

func centerOnNode(node: SKNode) {
let cameraPositionInScene: CGPoint = node.scene!.convert(node.position, from: worldNode)
node.parent!.run(SKAction.move(to: CGPoint(x:node.parent!.position.x - cameraPositionInScene.x, y:node.parent!.position.y - cameraPositionInScene.y), duration: 2.0))

}
``````

How can I have a camera follow a node all the way until the edge of the scene and stop once it reaches the end? I can’t figure out how to give the camera boundaries to stop at on the x axis.

Also, I want my player to be on the same y coordinate the entire game and just have him move horizontally(about 70% down on the screen). How do I implement my velocity to move him up the map, and still keep him on a constant y-axis value?

Here is all of my code:

``````class GameScene: SKScene, SKPhysicsContactDelegate {
var worldNode = SKNode()
var bgNode = SKNode()
var fgNode = SKNode()
var cameraNode: SKNode!
var background: SKNode!
var player: Character1Node!
var platform: SKTileMapNode!
var previousTranslateX: CGFloat = 0.0

override func didMove(to view: SKView) {
setupNodes()
self.anchorPoint = CGPoint(x: 0.5, y: 0.5)
cameraNode.position = CGPoint(x: size.width/2, y: size.height/2)

//Panning for dragging player
let pan = UIPanGestureRecognizer(target: self, action: #selector(GameScene.dragPlayer(sender:)))

print(worldNode.frame.size)
print(cameraNode.frame.size)
print(scene?.frame.size)
print(view.frame.size)
}

func dragPlayer(sender: UIPanGestureRecognizer) {

//retrieve pan movement along the x-axis of the view since the gesture began
let currentTranslateX = sender.translation(in: view!).x

//calculate translation since last measurement
let translateX = currentTranslateX - previousTranslateX

//move shape
player.parent!.position = CGPoint(x: player.parent!.position.x + (translateX*adjustment), y:player.parent!.position.y)

//reset previous measuremnt
if sender.state == .ended{
previousTranslateX = 0
} else {
previousTranslateX = currentTranslateX
}
}

func setupNodes(){

//Connecting variables to scene
worldNode = childNode(withName: "World")!
bgNode = worldNode.childNode(withName: "Background")!
background = bgNode.childNode(withName: "Overlay")!.copy() as! SKNode
fgNode = worldNode.childNode(withName: "Foreground")!
cameraNode = worldNode.childNode(withName: "Camera")

//Platform physics
platform = fgNode.childNode(withName: "Level1Map") as! SKTileMapNode
let bodySize = CGSize(width: 150, height: 190)
platform.physicsBody = SKPhysicsBody(rectangleOf: bodySize)
platform.physicsBody!.isDynamic = true
platform.physicsBody!.affectedByGravity = false
platform.physicsBody!.linearDamping = 0
platform.physicsBody!.velocity = CGVector(dx: 0, dy: 0)

enumerateChildNodes(withName: "//*", using: {node, _ in
if let customNode = node as? CustomNodeEvents {
customNode.didMoveToScene()
}
})

player = platform.childNode(withName: "//character1") as! Character1Node

}

override func update(_ currentTime: TimeInterval) {
let position = player.parent!.position

//Platform Tiles
let column = platform.tileColumnIndex(fromPosition: position)
let row = platform.tileRowIndex(fromPosition: position)
let objectTile = platform.tileDefinition(atColumn: column, row: row)
//print(objectTile)

if let _ = objectTile?.userData?.value(forKey: "tile2"){
print("jumping tile")
}

if let _ = objectTile?.userData?.value(forKey: "tile1"){
print("platform tile")
}

print(player.parent!.position)

}

override func didSimulatePhysics() {
cameraNode.position = CGPoint(x: player.parent!.position.x, y: player.parent!.position.y)
self.centerOnNode(node: cameraNode)
}

func centerOnNode(node: SKNode) {
let cameraPositionInScene: CGPoint = node.scene!.convert(node.position, from: worldNode)
node.parent!.run(SKAction.move(to: CGPoint(x:node.parent!.position.x - cameraPositionInScene.x, y:node.parent!.position.y - cameraPositionInScene.y), duration: 2.0))

}
``````

I can’t test any code to put up a functional reply but check against the edges of the camera with something like this

public func checkCamera(camera: SKCamera) {
if camera.position - camera.size.width < 0 {
return true
} else if camera.position + camera.size.width > scene.size.width {
return true
} else { return false }
}

then if it returns true don’t move the camera