How to Make Camera Follow Sknode in Sprite Kit

How to make camera follow SKNode in Sprite Kit?

Something like this should help. I call the following from my didSimulatePhysics.

-(void)centerOnNode:(SKNode*)node {
CGPoint cameraPositionInScene = [node.scene convertPoint:node.position fromNode:node.parent];
cameraPositionInScene.x = 0;
node.parent.position = CGPointMake(node.parent.position.x - cameraPositionInScene.x, node.parent.position.y - cameraPositionInScene.y);
}

Swift Spritekit Camera Follow skspritenode(Player)

The easiest way to make the camera always follow the player, is to make the camera a child of the player, that just assign this camera to the scene. Then if you need to take focus away from the player, have another camera set up, so that you can swap.

If you want the camera to only follow the player on the y axis, then make sure that player and camera are siblings to the same parent node, and on your didFinishUpdate method, just add camera.position.y = player.position.y

Alternative:
If player is a subclass of SKSpriteNode, you could always override the position property, and set the camera in there:

override var position : CGPoint
{
didSet
{
scene?.camera?.position.y = position.y //Yes we want to use ? because we do not know if there is a scene when changing the position of this sprite
}
}

SpriteKit: How can I make my HUD following my camera?

Instead of adding the jump button as a child of the scene, add it as a child of your camera node. Just like other nodes, SKCameraNode's children always follow the parent.

So instead of:

self.addChild(jump)

use:

cameraNode.addChild(jump)

Swift Sprite Kit Camera Movement

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))
}

How to do a camera movement in spriteKit

In the example from Apple's Documentation, which you are following the camera node isn't an SKSprite, it's an SKNode. I think that will fix your problem.

To answer the question from the title, what you're essentially doing is attaching a world node to the scene. Inside this node, all the sprites are placed. As a child to the world node you add another node for the camera.

This gives you three distinct coordinate systems. Imagine, three sheets of paper, the bottom most one is your world, ie the layer with all the sprites. On top of that is a small piece of paper that represents the camera. Above all of this you have a transparent box that represents your viewing area.

The way it's set up it's impossible to move the top most transparent viewing layer. Instead, what you're doing is moving the point that's sits on top of the world layer and then sliding the world layer to that point.

Now imagine, in the paper scenario, this is a 2D scrolling world where you can only go left and right. Now take the camera point and put it all the way to the right most side of the viewing area. Now, take the world layer and drag it to the left until the camera is in the center of the non-moveable viewing area. That is more or less, what's happening.

Moving Camera in SpriteKit Swift

As an alternative to @Kris's solution (which is based in UIKit), you can also monitor touches in Sprite Kit with your SKScene subclass. I wrote a small sample which should point you in the right direction.

class YourSceneSubclass : SKScene
{
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
guard let touch = touches.first else {
return
}

let location = touch.locationInNode(self)
let previousLocation = touch.previousLocationInNode(self)

camera?.position.x += location.x - previousLocation.x
camera?.position.y += location.y - previousLocation.y
}
}

I didn't run this, just wrote it in a playground. Also note that if you want to handle other taps/gestures as well you will have to write additional code making sure the recognition works well for all your intended scenarios.



Related Topics



Leave a reply



Submit