12
votes

I want to have background stationary with different objects (sprites and other objects).

Player will be represented by center node that will move around the world. I want to have my camera pinned to central node, e.g. the world should move and the camera should stay stationary.

How do I achieve that?

6
Check the adventure game guide section on scrolling: developer.apple.com/library/ios/documentation/GraphicsAnimation/…LearnCocos2D
This link might also help you out67cherries

6 Answers

18
votes

The new SKCameraNode seems like a very easy way to do this.

https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKCameraNode/

Simply

1) create an SKCameraNode

// properties of scene class
let cam = SKCameraNode()
let player = SKSpriteNode()

2) add it to your scene camera property

// In your scene, for instance didMoveToView
self.camera = cam

3) make the camera follow your player position

override func update(currentTime: CFTimeInterval)
{
    /* Called before each frame is rendered */
    cam.position = player.position
}
14
votes

I realize this is similar to Stuart Welsh's answer; however, I'd like to make his good answer a bit more comprehensive.

Basically, Apple recommends that you create a "world" node to contain all of your other nodes, with the world being a child of the actual scene; and further that you create a "camera" node as a child of the world node.

Then, from your scene, you can do something like:

[self centerOnCameraNamed:myCameraName];

Which calls the method (also in your scene):

- (void)centerOnCameraNamed:(NSString*)cameraName
{
  SKNode* world = [self childNodeWithName:worldName];
  SKNode* camera = [world childNodeWithName:cameraName];
  CGPoint cameraPositionInScene = [camera.scene convertPoint:camera.position fromNode:world];
  world.position = CGPointMake(world.position.x - cameraPositionInScene.x, world.position.y - cameraPositionInScene.y);
}
6
votes

Something like this should help. I call the following from my didSimulatePhysics.

-(void)centerOnNode:(SKNode*)node {
    CGPoint cameraPositionInScene = [node.scene convertPoint:node.position fromNode:node.parent];
    cameraPositionInScene.x = 0;
    node.parent.position = CGPointMake(node.parent.position.x - cameraPositionInScene.x, node.parent.position.y - cameraPositionInScene.y);
}
3
votes

There are few ways to make a camera follow SKNode. It depends on preferred type of scrolling.

  1. A camera is rigidly attached (like in shooters)
  2. A camera for vertical or horizontal scrolling (like in platformers)

A camera can be rigidly attached by adding it as child node of player:

let player = SKNode()
let camera = SKCameraNode()

override func didMove(to view: SKView) {
      addChild(player)
      player.addChild(camera)
}

It is important to note that position of camera should be corrected after all physics updates will be completed. Otherwise a screen can shakes if player or other object which the camera are followed moves with big velocity. It depends on order of updating of scene nodes and position of camera in node ieararchy. To avoid of this effect it's necessary to update position of camera in method didSimulatePhysics:

let player = SKNode()
let camera = SKCameraNode()

override func didMove(to view: SKView) {
      addChild(player)
      addChild(camera)
}

// Vertical scrolling, moving only in y-axis
override func didSimulatePhysics() {
    camera.position.y = player.position.y
}

// Horizontal scrolling, moving only in x-axis
// override func didSimulatePhysics() {
//    camera.position.x = player.position.x
// }
3
votes

Using SKCameraNode with SKConstraint in Swift 5.1

let camera = SKCameraNode()
camera.constraints = [.distance(.init(upperLimit: 10), to: node)]
scene.addChild(camera)
scene.camera = camera
1
votes
let cam = SKCameraNode()
var player: SKSpriteNode?

override func didMoveToView(view: SKView) {
    /* Setup your scene here */
    self.camera = cam
    player = SKSpriteNode(imageNamed: "Player")
    if player?.position != nil {
        player!.position = CGPoint(x: size.width / 2, y: size.height - 150)
        self.addChild(player!)
    }
    player?.addChild(cam)
}