Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sprite Kit Camera on Node

I made a platform game and pointed the camera on the main node Player.

I have gone through the Apple document which can be found here: Apple

There are around 6 Platforms, with self.frame.size.height / 4.5 space between them, which should respawn everytime they are under dy = -15 on the top of the screen again, to make it an infinite loop.

I got a the Player node, which gets an impulse everytime the screen is touched (Player jumps up and down). The whole game does only move on the y-Axis.

The camera I created is focused on the Player, everytime the Player jumps the platforms move down and the Player moves up. However, this is only the View, and not the real world's position. That means, the given positions in SpawnPlatforms are always the same, because they dont move, only the View that is stick to the Player moves up and down.

I want to have the Camera on my Player Node, which moves on the y-Axis, and while it goes further up, the Platforms should also move down, at the moment only the view changes and I can't work with the Updated:Method to respawn the Platforms. How can I change that?

Edit: I got my Code working with the update in the Update:Method, but this still doesn't answer my initial Question, how to move the whole world with the Camera, not only the Camera.

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

    self.physicsWorld.contactDelegate = self
    self.anchorPoint = CGPoint(x: 0, y: 0.30)

    backgroundColor = SKColor(red: 81.0/255.0, green: 192.0/255.0, blue: 201.0/255.0, alpha: 1.0)

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

    self.Camera = SKNode()
    self.Camera.name = "Camera"
    self.World.addChild(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: -36)
    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)

    ....//Same code for the other Platforms1-5
    }

    func SpawnPlayer(){

    Player = SKSpriteNode (imageNamed: "Image.png")
    Player.size = CGSize(width: 64, height: 64)
    Player.position = CGPoint(x: self.frame.size.width / 2, y: 0)
    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?.categoryBitMask = PlayerCategory
    Player.physicsBody?.collisionBitMask = Platform0Category
    Player.physicsBody?.contactTestBitMask = Platform0Category | Platform1Category | Platform2Category | Platform3Category | Platform4Category | Platform5Category

    World.addChild(Player)

}

override func didSimulatePhysics() {

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

    self.centerOnNode(Camera!)

}

func centerOnNode(node: SKNode) {

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

    World.runAction(SKAction.moveTo(CGPoint(x:World.position.x , y:World.position.y - cameraPositionInScene.y), duration: 1.0))

}

override func update(currentTime: CFTimeInterval) {
    /* Called before each frame is rendered */

    if(Player.position.y > (Platform3.position.y + 30) && Player.position.y < Platform4.position.y){
        Platform1.position = CGPointMake(self.frame.size.width / 2, Platform6.position.y + self.frame.size.height / 4.5)
        Platform1.color = SKColor.redColor()
    }

    ...//Same code for the other Platforms1-5
 }
like image 996
Albert Avatar asked Jul 01 '15 10:07

Albert


2 Answers

Create a SKNode and let's call it map. Add the map as a child of this scene. You add every other game node as a child of this map (platforms, player, etc).

Then, instead of moving node.parent, you move the map. This will cause that the platforms has always the same position even though you move the camera.

Plus, you can add game menus to the scene and they will not move, but the map will.

For example, the next code will move the map in update: method with a linear velocity:

kScrollScenarioFactor may be like 200.f

-(void)update:(CFTimeInterval)currentTime {
  //Calculating time for realistic scroll speed
  float scrollTime = currentTime - self.lastTime;
  self.lastTime = currentTime;
  self.map.position = CGPointMake(map.position.x - (scrollTime * self.kScrollScenarioFactor), map.position.y);
}

Or if you want to move the map depending on player inside update: method, you can look at this approach:

-(void)update:(CFTimeInterval)currentTime {
  //Calculating playerPosition difference
  float diffX = self.lastPlayerPosition.x - self.player.position.x;
  float diffY = self.lastPlayerPosition.y - self.player.position.y;
  self.lastPlayerPosition = self.player.position;

  //Updating map position
  self.map.position = CGPointMake(map.position.x + diffX, map.position.y + diffY);
}
like image 126
aramusss Avatar answered Nov 15 '22 19:11

aramusss


If you have a scrolling background then make three layers in the game:

  • Foreground Layer: Contains the player, platform, and any other in game nodes.
  • Background Layer: Contains the backgrounds which move a certain amount as the player moves.
  • HUD: For all the scoring relating nodes which will remaining at their positions regardless of the background and player positions.

Now, as per my understanding of your problem, all your platforms have predefined positions in the scene, which do not change. Only the position of the player node changes and hence you want the camera node to follow the player and move the world with it. If this is the case then you could try this:

SKNode’s have no visual content, but do have a position in the scene. This means you can move the node around and its child nodes will move with it

Initially add the following class properties -

var backgroundNode: SKNode!
var foregroundNode: SKNode!
var hudNode: SKNode!

var player: SKNode!
var platformType: PlatformType!

//Add Background node

 func createBackgroundNode() -> SKNode {
    let backgroundNode = SKNode()
    let node = SKSpriteNode(imageNamed:"")

    node.position = CGPoint(x: xPosition , y: yPosition)
    backgroundNode.addChild(node)

    return backgroundNode
}

Then call this in Game Scene

backgroundNode = createBackgroundNode()
addChild(backgroundNode)

Now to Add the player:

func createPlayer() -> SKNode {
  let playerNode = SKNode()
  playerNode.position = CGPoint(x: x.position, y: y.position)

  let sprite = SKSpriteNode(imageNamed: "Player")
  playerNode.addChild(sprite)

  return playerNode
}

In order to add the player, we will create the foreground layer and then add it to it. Put this just below where you added backgroundNode.

foregroundNode = SKNode()
addChild(foregroundNode) 

player = createPlayer()
foregroundNode.addChild(player)

Finally, the platform that you want to add, you can add it as:

func createPlatformAtPosition(position: CGPoint) -> PlatformNode {

  let node = PlatformNode()
  let thePosition = CGPoint(x: position.x, y: position.y)
  node.position = thePosition
  node.name = "NODE_PLATFORM"

  var sprite: SKSpriteNode
  sprite = SKSpriteNode(imageNamed: "Platform")
  node.addChild(sprite)

  return node
} 

Lastly add this to Game Scene under foregroundNode.addChild(player)

  let platform = createPlatformAtPosition(CGPoint(x: 300, y: 270)
  foregroundNode.addChild(platform)

Hope this helps you a little.

like image 30
Mehul Avatar answered Nov 15 '22 18:11

Mehul