1
votes

I made a Camera in Sprite Kit focusing on a SKSpriteNode.

There is a great Document by Apple: Apple Document

However, the camera as it now is follows the SKSpriteNode immediately, while I want to have a little leeway.

For e.g. the SKSpriteNode moves up and down after a touch is made, the camera follows the SKSpriteNode slowly from its origin point, and the maximum distance Height for the SKSpriteNode is half of the screen, and when the SKSpriteNode stands still, the camera and the SKSpriteNode move again to their origin point.

Also the PhysicBody's of the Nodes behave strangely, moving away from its actual image. How can I fix that ?

Here is my Code:

class GameScene: SKScene, SKPhysicsContactDelegate {

var Player: SKSpriteNode!

var Platform0: SKSpriteNode!
var Platform1: SKSpriteNode!
var Platform2: SKSpriteNode!
var Platform3: SKSpriteNode!
var Platform4: SKSpriteNode!
var Platform5: SKSpriteNode!

var World: SKNode!
var Camera: SKNode!

override func didMoveToView(view: SKView) {
    /* Setup your scene here */

    self.physicsWorld.contactDelegate = self
    self.anchorPoint = CGPoint(x: 0.5, y: 0.1)

    self.World = SKNode()
    self.World.name = "World"
    addChild(self.World)
    self.Camera = SKNode()
    self.Camera.name = "Camera"
    self.World.addChild(self.Camera)

    SpawnPlatforms()
    SpawnPlayer()
}

func SpawnPlatforms() {

    Platform0 = SKSpriteNode (color: SKColor.greenColor(), size: CGSize(width: self.frame.size.width , height: 25))
    Platform0.position = CGPoint(x: self.frame.size.width / 2, y: 40)
    Platform0.zPosition = 1

    Platform0.physicsBody = SKPhysicsBody(rectangleOfSize:Platform0.size)
    Platform0.physicsBody?.dynamic = false
    Platform0.physicsBody?.allowsRotation = false
    Platform0.physicsBody?.restitution = 0
    Platform0.physicsBody?.usesPreciseCollisionDetection = true

    Platform0.physicsBody?.categoryBitMask = Platform0Category
    Platform0.physicsBody?.collisionBitMask = PlayerCategory
    Platform0.physicsBody?.contactTestBitMask = PlayerCategory

    World.addChild(Platform0)

    /// All other Platforms declared as the same above

}

func SpawnPlayer(){

    var Player1:SKTexture!
    var Player2:SKTexture!

    var Animation:SKAction!
    var AnimationRepeat:SKAction!

    Player1 = SKTexture(imageNamed: "Image.png")
    Player1.filteringMode = .Nearest
    Player2 = SKTexture(imageNamed: "Image2.png")
    Player2.filteringMode = .Nearest

    Animation = SKAction.animateWithTextures([Player1,Player2], timePerFrame: 0.5)
    AnimationRepeat = SKAction.repeatActionForever(Animation)

    Player = SKSpriteNode (imageNamed: "Image.png")
    Player.size = CGSize(width: 64, height: 64)
    Player.position = CGPoint(x: self.frame.size.width / 2, y: 80)
    Player.zPosition = 2

    Player.physicsBody = SKPhysicsBody(rectangleOfSize:CGSize(width: 35, height: 50))
    Player.physicsBody?.dynamic = true
    Player.physicsBody?.allowsRotation = false
    Player.physicsBody?.restitution = 0
    Player.physicsBody?.usesPreciseCollisionDetection = true
    Player.physicsBody?.velocity = CGVector(dx: 0, dy: -0.1)

    Player.physicsBody?.categoryBitMask = PlayerCategory
    Player.physicsBody?.collisionBitMask = Platform0Category
    Player.physicsBody?.contactTestBitMask = Platform0Category | Platform1Category | Platform2Category | Platform3Category | Platform4Category | Platform5Category

    Player.runAction(AnimationRepeat)
    World.addChild(Player)

}

override func didFinishUpdate() {

    Camera.position = CGPoint(x: Player.position.x, y: Player.position.y)
    self.centerOnNode(Camera)

}

func centerOnNode(node: SKNode) {

    let cameraPositionInScene: CGPoint = node.scene!.convertPoint(node.position, fromNode: World)

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

}
1

1 Answers

5
votes

Instead of directly declaring the position in centeronnode, use SKAction moveTo.

It has a duration value.

Replace your old centerOnNode func with:

func centerOnNode(node: SKNode) {

    let cameraPositionInScene: CGPoint = node.scene!.convertPoint(node.position, fromNode: World)

    node.parent!..runAction(SKAction.moveTo(CGPoint(x:node.parent!.position.x - cameraPositionInScene.x, y:node.parent!.position.y - cameraPositionInScene.y), duration: 1))

}

That should work, but I have't tested it sorry.

Update for Swift 3


func centerOnNode(node: SKNode) {
    let cameraPositionInScene: CGPoint = node.scene!.convert(node.position, from: World)   
    node.parent!.run(SKAction.move(to: CGPoint(x:node.parent!.position.x - cameraPositionInScene.x, y:node.parent!.position.y - cameraPositionInScene.y), duration: 1))   
}