Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

zPosition of SKNode relative to its parent?

I always thought that the the zPosition of a SKNode would be relative to its parent, but right now I'm experiencing the opposite effect.

I have two parent SKNodes in my scene, which have a zPosition of 1 (node1) and 2 (node2). What I want to achieve is that node2 should ALWAYS be layered ABOVE node1. But unfortunately, the child nodes of node1 (which have a zPosition of 1-50) are all layered above the child nodes of node2 (which currently have no zPosition). Is there any way to solve this (except giving node2 a zPosition of more than 50)? Maybe some kind of boolean Parameter to set all child nodes' zPosition relative to its parent? Any help will be appreciated!

EDIT: To make it more clear, here's the hierarchy of all elements:

  • node1:SKNode (zPosition 1)
    • child1:SKNode (zPosition 1)
    • child2:SKNode (zPosition 2)
    • child3:SKNode (zPosition 3)
    • ...
    • child50:SKNode(zPosition 50)
  • node2:SKNode (zPosition 2)
    • child1:SKLabelNode (no zPosition)
    • child2:SKLabelNode (no zPosition)
    • child3:SKLabelNode (no zPosition)
    • ...
    • child50:SKLabelNode (no zPosition)

EDIT2: Here's a very reduced version of my GameScene class:

import SpriteKit

class GameScene: SKScene {

    let gameNode = SKNode()
    let node1 = SKNode()
    let node2 = SKNode()

    let nodeSize:CGFloat = 50.0
    let spacing:CGFloat = 5.0

    required init(coder aDecoder: NSCoder) {
        fatalError("NSCoder not supported")
    }

    override init(size: CGSize) {
        super.init(size: size)

        self.addChild(gameNode)

        node1.name = "node1"
        node2.name = "node2"

        node1.zPosition = 1
        node2.zPosition = 2

        gameNode.addChild(node1)
        gameNode.addChild(node2)

        // add children to node1
        for i in 1..<10 {
            let child = SKSpriteNode(color: UIColor.redColor(), size: CGSize(width: nodeSize, height: nodeSize))
            child.position = CGPointMake((nodeSize + spacing) * CGFloat(i), 0)
            child.zPosition = CGFloat(i)
            self.node1.addChild(child)
        }

        // add children to node2
        for i in 1..<10 {
            let child = SKLabelNode(fontNamed: "Avenir Black")
            child.position = CGPoint(x: (nodeSize + spacing) * CGFloat(i), y: 0)
            child.text = "label\(i)"
            child.fontSize = 10
            child.fontColor = UIColor.blackColor()
            self.node2.addChild(child)
        }
    }
}

When you run it, you can see that only the first child of node2 (label1) is layered above the first child of node1 (since they have the same zPosition). All others are layered underneath the children of node1.

like image 293
biedert Avatar asked Jul 22 '15 08:07

biedert


1 Answers

When reading the Apple Documentation regarding this, you can find:

Maintaining the order of a node’s children can be a lot of work. Instead, you can give each node an explicit height in the scene. You do this by setting a node’s zPosition property. The z position is the node’s height relative to its parent node, much as a node’s position property represents its x and y position relative to parent’s position. So you use the z position to place a node above or below the parent’s position.

When you take z positions into account, here is how the node tree is rendered:

  • Each node’s global z position is calculated.
  • Nodes are drawn in order from smallest z value to largest z value.
  • If two nodes share the same z value, ancestors are rendered first, and siblings are rendered in child order.

The point I found - which i didn't know it was like this - is that the children zPosition is calculated summating their parents zPosition, so if node1.zPosition + (node1's)child3.zPosition = 4, and node2.zPosition + (node2's)child3.zPosition = 3, the node1's child will be painted above.

Solution: Set node2.zPosition bigger than (node1's)lastChild.zPosition + node1.zPosition.

like image 73
aramusss Avatar answered Jan 03 '23 19:01

aramusss