Gerome Pistre
Gerome Pistre

Reputation: 467

Spritekit -- keep scene centered on sprite above certain height

In my game, the camera is centered on the hero, but only in the x axis. The camera (the scene) moves with him when he moves left or right, but stays the same when he jumps.

The setup can be reproduced simply like this:

import SpriteKit

class GameScene: SKScene {

    let ship = SKSpriteNode(imageNamed: "Spaceship")
    let ground = SKShapeNode(rectOfSize: CGSizeMake(600, 30))

    let world = SKNode()

    override func didMoveToView(view: SKView) {

        self.anchorPoint = CGPointMake(0.5, 0.5)

        self.ship.setScale(0.2)
        self.ship.physicsBody = SKPhysicsBody(circleOfRadius: self.ship.size.width / 2)

        self.ground.position = CGPointMake(0, -200)
        self.ground.fillColor = SKColor.redColor()
        self.ground.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(600, 30))
        self.ground.physicsBody?.dynamic = false

        world.addChild(self.ship)
        world.addChild(self.ground)

        self.addChild(world)
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.ship.physicsBody?.applyImpulse(CGVectorMake(0, 60))
    }

    override func didFinishUpdate() {
        let cameraPositionInScene = self.convertPoint(self.ship.position, fromNode: world)

        // the position is updated only in the x axis
        self.world.position = CGPointMake(self.world.position.x - cameraPositionInScene.x,
                                          self.world.position.y)
    }
}

However, I'd like the camera to move in the y axis once the hero reaches a certain height (so that he can continue to go higher in case a level goes up "in the clouds").

I tried changing the position update in the didFinishUpdate() function to this :

if self.ship.position.y > 100 {
        self.world.position = CGPointMake(self.world.position.x - cameraPositionInScene.x,
                                          self.world.position.y - cameraPositionInScene.y)
    } else {
        self.world.position = CGPointMake(self.world.position.x - cameraPositionInScene.x,
                                          self.world.position.y)
    }

And it indeed starts following the ship above a certain height, but never completely goes back to its original position, and I haven't been able to figure out why.

Upvotes: 0

Views: 76

Answers (1)

CloakedEddy
CloakedEddy

Reputation: 1995

In your didFinishUpdate() method, you are changing the world's y-coordinate only when the ship's y-coordinate is above 100. In the scenario where the ship descends from 105 to 95, the world's y coordinate is no longer updated.

I expect removing the if-statement and always updating the world position to take your camera position into account to help you.

EDIT:
I've come up with some sample code, and I'm going use SKCameraNode because I really think this will save you headaches in the future. I didn't run this, so you might have to offset something here and there. I have written code for such camera functionality both with and without SKCameraNode, and it is a nice class that the framework gives you basically for free.

override func didMoveToView(view: SKView) {
  // ...
  camera = SKCameraNode()
  // ...
}

override func didFinishUpdate() {
  var cameraPosition = CGPointMake(self.ship.position)
  cameraPosition.y = MAX(0,cameraPosition.y - 100)
  self.camera.position = cameraPosition
}

Upvotes: 1

Related Questions