4

I am creating a Terraria-style game in Swift. I want to have it so the player node is always in the center of the screen, and when you move right the blocks go left like in Terraria.

I am currently trying to figure out how to keep the view centered on the character. Does anyone know of a good way of accomplishing this?

William Price
  • 4,033
  • 1
  • 35
  • 54
bob
  • 175
  • 2
  • 6

3 Answers3

9

Since iOS 9 / OS X 10.11 / tvOS, SpriteKit includes SKCameraNode, which makes a lot of this easier:

  • positioning the camera node automatically adjusts the viewport
  • you can easily rotate/zoom the camera by transform in the camera node
  • you can fix HUD elements relative to the screen by making them children of the camera node
  • the scene's position stays fixed, so things like physics joints don't break the way they do when you emulate a camera by moving the world

It gets even better when you combine camera nodes with another new feature, SKConstraint. You can use a constraint to specify that the camera's position is always centered on a character... or add extra constraints to say, for example, that the camera's position must stay within some margin of the edge of the world.

rickster
  • 124,678
  • 26
  • 272
  • 326
  • Where do you suggest smoothly animating SKCameraNode to new positions (i.e., only move camera if node moves at least 50 pixels)? It doesn't seem to work when done inside SKScene's `update(_ currentTime: CFTimeInterval)` function? – Crashalot Dec 04 '16 at 22:49
  • @Crashalot sounds like something good to post as its own question. – rickster Dec 05 '16 at 05:08
  • OK will do, was just hoping you would answer instead of a random person from the community, that's all :) you're one of the best re spritekit questions! – Crashalot Dec 05 '16 at 06:01
  • Here's the question if you get a moment: http://stackoverflow.com/questions/40969539/spritekit-how-to-smoothly-track-node-with-skcameranode-but-only-after-node-move Thanks so much for your help! – Crashalot Dec 05 '16 at 07:54
  • Hi rickster, if you get a chance would love your input on how to smoothly move the camera, where the camera only moves when a fast node moves a certain number of pixels. It seems to have stumped everyone else so far: http://stackoverflow.com/questions/40969539/spritekit-how-to-smoothly-animate-skcameranode-while-tracking-node-but-only-aft – Crashalot Dec 08 '16 at 04:27
5

The below will center the camera on a specific node. It can also smoothly transition to the new position over a set time frame.

class CameraScene : SKScene {
    // Flag indicating whether we've setup the camera system yet.
    var isCreated: Bool = false
    // The root node of your game world. Attach game entities 
    // (player, enemies, &c.) to here.
    var world: SKNode?
    // The root node of our UI. Attach control buttons & state
    // indicators here.
    var overlay: SKNode?
    // The camera. Move this node to change what parts of the world are visible.
    var camera: SKNode?

    override func didMoveToView(view: SKView) {
        if !isCreated {
            isCreated = true

            // Camera setup
            self.anchorPoint = CGPoint(x: 0.5, y: 0.5)
            self.world = SKNode()
            self.world?.name = "world"
            addChild(self.world)
            self.camera = SKNode()
            self.camera?.name = "camera"
            self.world?.addChild(self.camera)

            // UI setup
            self.overlay = SKNode()
            self.overlay?.zPosition = 10
            self.overlay?.name = "overlay"
            addChild(self.overlay)
        }
    }


    override func didSimulatePhysics() {
        if self.camera != nil {
            self.centerOnNode(self.camera!)
        }
    }

    func centerOnNode(node: SKNode) {
        let cameraPositionInScene: CGPoint = node.scene.convertPoint(node.position, fromNode: node.parent)

        node.parent.position = CGPoint(x:node.parent.position.x - cameraPositionInScene.x, y:node.parent.position.y - cameraPositionInScene.y)
    }

}

Change what’s visible in the world by moving the camera:

// Lerp the camera to 100, 50 over the next half-second.
self.camera?.runAction(SKAction.moveTo(CGPointMake(100, 50), duration: 0.5))

Source: swiftalicio - 2D Camera in SpriteKit

For additional information, look at Apple's SpriteKit Programming Guide (Example: Centering the Scene on a Node).

Sergio Toledo Piza
  • 793
  • 1
  • 6
  • 27
sangony
  • 11,636
  • 4
  • 39
  • 55
0

You have to create World node that contains nodes. And you should put anchorPoint for example (0.5,0.5). Center on your player. And then you should move your player.

func centerOnNode(node:SKNode){

   let cameraPositionInScene:CGPoint = self.convertPoint(node.position, fromNode: world!)
   world!.position = CGPoint(x:world!.position.x - cameraPositionInScene.x, y: world!.position.y - cameraPositionInScene.y)
}


override func didSimulatePhysics() {
  self.centerOnNode(player!)
}
Darvas
  • 974
  • 3
  • 14
  • 27