Swift: Positioning Children of the SKCameraNode

1.1k Views Asked by At

Context:

  • there is a cursor (like your mouse) SKSpriteNode
  • cam is a SKCameraNode and is a child to the cursor (i.e. wherever your cursor goes, so follows the camera).
  • cam is purposely not centered on the cursor; rather, it is offset so the cursor appears at the top of the view, and there remains empty space below

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
        ...
2

There are 2 best solutions below

13
On BEST ANSWER

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.

0
On

the cameraNode has no size, but you can get the current screen size with the frame property

frame.size

then you can position your node accordingly, for example if you want to position the center of yournode in the left corner you set the position as this:

yournode.position.x = 0
yournode.position.y = frame.size.height