# Working with Cameras in SpriteKit Game

**URL:** <https://forums.kodeco.com/t/working-with-cameras-in-spritekit-game/20410>\
**Category:** Sprite Kit\
**Created:** [September 27, 2016, 8:38pm UTC](https://forums.kodeco.com/t/working-with-cameras-in-spritekit-game/20410 "2016-09-27T20:38:54Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![jzt5061](https://assets.chunter.kodeco.com/user_avatar/forums.kodeco.com/jzt5061/32/62748_2.png) [@jzt5061](https://forums.kodeco.com/u/jzt5061)\
**Post date:** [September 27, 2016, 8:38pm UTC](https://forums.kodeco.com/t/working-with-cameras-in-spritekit-game/20410/1 "2016-09-27T20:38:54Z")

</div>

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:)))
    self.view?.addGestureRecognizer(pan)
    
    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
    let adjustment:CGFloat = 2.0
    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!.categoryBitMask = PhysicsCategory.Platform
    platform.physicsBody!.collisionBitMask = PhysicsCategory.None
    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))
    
}

```

---

<div class="post-metadata">

**Author:** ![xc\_pika](https://assets.chunter.kodeco.com/user_avatar/forums.kodeco.com/xc_pika/32/81494_2.png) [@xc\_pika](https://forums.kodeco.com/u/xc_pika)\
**Post date:** [December 8, 2019, 11:54am UTC](https://forums.kodeco.com/t/working-with-cameras-in-spritekit-game/20410/2 "2019-12-08T11:54:57Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![melody242](https://s3.amazonaws.com/cdn.raywenderlich.com/community/forum-assets/noun-game-ghost-878668.png) [@melody242](https://forums.kodeco.com/u/melody242)\
**Post date:** [October 14, 2024, 8:44am UTC](https://forums.kodeco.com/t/working-with-cameras-in-spritekit-game/20410/3 "2024-10-14T08:44:18Z")

</div>

> [@jzt5061](#):
>
> 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.
> 
> ```auto
> 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:
> 
> ```auto
> 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:)))
> self.view?.addGestureRecognizer(pan)
>     
> 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
> let adjustment:CGFloat = 2.0
> 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!.categoryBitMask = PhysicsCategory.Platform
> platform.physicsBody!.collisionBitMask = PhysicsCategory.None
> 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))
>     
> }
> 
> ```

To achieve a camera that follows the player horizontally until the edge of the scene and keeps the player [GMSocrates](https://www.gm-socrates.com/) at a constant y-coordinate, calculate camera boundaries, constrain camera movement, adjust player velocity, and set player’s y-position. Remember to replace placeholder values with your desired values.
