Search code examples
iossprite-kitskspritenodesksceneskcameranode

SpriteKit: static background in the scene with moving SKCameraNode


My goal is to have a static node in the background of the SKScene. In this scene, I use SKCameraNode to pan around as needed.

The background node has to be static because it presents the sky in far distance which is expected not to move.

Problem:

If I would simply add the background node as a child to the scene, I would have to move the background in the same way the camera is panned, in order to have background always fully visible inside camera's viewport. I don't want to do that because the background node has some visual effects and filters applied to it and therefore moving it causes performance drop.

What I want, is having background laid out in the background as a static node or view, which would not have to be moved in order to "follow" the camera.

What have I tried:

I know that a node can be added as a child to SKCameraNode in order to make sure it follows the camera. But as Apple suggests, this is useful for HUD elements like score labels, etc., which are usually rendered above everything. This is of course not applicable if you want to add background, since I want it to be in the background, behind the nodes that are added as child nodes directly to the scene.

Even though, I tried adding background node as a child to camera node and play with z position and things like that, but nothing helped, as expected.

I also tried adding background as a subview to root SKView but I wasn't able to get it rendered behind the scene for some reason.

Thanks in advance.


Solution

  • Edit: Never mind my first answer was a dead end. The following works though and is seems to be something you've already attempted: Adding the background as a child to the camera.

    I guess you've just have been having some problems with the zPosition. The below proof of concept works as intended as far as I can tell.

    class GameScene: SKScene {
        let cameraNode = SKCameraNode()
    
        override func didMoveToView(view: SKView) {
            let center = CGPointMake(view.frame.size.width/2, view.frame.size.height/2)
    
            cameraNode.position = center
            addChild(cameraNode)
            camera = cameraNode
            let background = SKSpriteNode(color: SKColor.orangeColor(), size: view.frame.size)
            cameraNode.addChild(background)
    
            let sprite = SKSpriteNode(color: SKColor.redColor(), size: CGSizeMake(100, 100))
            sprite.position = center
            addChild(sprite)
        }
    
        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
            let move = SKAction.moveBy(CGVectorMake(200, 0), duration: 2)
            cameraNode.runAction(move)
        }
    }