iosswiftsprite-kitskspritenodeskcameranode

Swift: Positioning Children of the SKCameraNode


Context:

A simple schematic is given below enter image description here

Goal: The goal is two add to sprites to the lower left and lower right corners of the camera's view. The sprites will be children of the camera, so that they always stay in view.

Question

How can I position a sprite in the corner of a camera, especially given that the SKSpriteNode does not have an anchorPoint attribute (as an SKSpriteNode typically has, which let me offset the camera as a child to the cursor)?

Note: One can position the SKSpriteNodes on the GameScene and then call .move(toParent: SKNode), which gets you closers but also messes with the position and scale of the SKSpriteNodes

var cam: SKCameraNode!
let cursor = SKSpriteNode(imageNamed: "cursor")

    override func didMove(to view: SKView) {

        // Set up the cursor
        cursor.setScale(spriteScale)
        cursor.position = CGPoint(x: self.frame.midX, y: raisedPositioning)
        cursor.anchorPoint = CGPoint(x:0.5, y:0.5)
        cursor.zPosition = CGFloat(10)
        addChild(cursor)

        // Set up the camera
        cam = SKCameraNode()
        self.camera = cam
        cam.setScale(15.0)
        
        // Camera is child of Cursor so that the camera follows the cursor
        cam.position = CGPoint(x: cursor.size.width/2, y: -(cursor.size.height * 4))
        cursor.addChild(cam)

        // Add another sprite here and make it child to cursor
        ...

Solution

  • This is best solved with a "dummy node" that acts as the camera's screen space coordinates system.

    Place this dummy node at the exact centre of the view of the camera, at a zPosition you're happy with, as a child of the camera.

    ...from SKCameraNode docs page:

    The scene is rendered so that the camera node’s origin is placed in

    the middle of the scene.

    Attach all the HUD elements and other pieces of graphics and objects you want to stay in place, relative to the camera, to this dummy object, in a coordinate system that makes sense relative to the camera's "angle of view", which is its frame of view.

    ...from a little further down the SKCameraNode docs page:

    The camera’s viewport is the same size as the scene’s viewport (determined by the scene’s size property) and the scene is still scaled by its scaleMode property when it is rendered into the view.

    Whenever the camera moves, it moves the dummy object, and all the children of the dummy object move with the dummy object.

    The biggest advantage of this approach is that you can shake or otherwise move the dummy object to create visual effects indicative of motion and explosions. But also a neat system for removal from view, too.