0
votes

In SpriteKit, if some nodes share the same zPosition, then the nodes are rendered in the order they were added to the scene so that the latest node added will be on top of the other ones (as long as the ignoresSiblingOrder scene property is set to false).

I am wondering if there is a way to know the order in which SpriteKit is going to render the nodes that share the same zPosition, so that I can give then an explicit zPosition.

Thank you.

1

1 Answers

2
votes

Premise

When you add a child to an SKNode it gets added at the end of the children array property. (At least this what I found running a few tests).

Solution

So you can scroll all the children of a given node and group them by zPosition. You'll get a dictionary where the key is the zPosition and the value is an ordered list of nodes (from the oldest insertion to the most recent).

Extension

extension SKNode {
    func childrenByZPosition() -> [CGFloat:[SKNode]] {
        return children.reduce([CGFloat:[SKNode]]()) { (var accumulator, node) -> [CGFloat:[SKNode]] in
            var list = accumulator[node.zPosition] ?? [SKNode]()
            list.append(node)
            accumulator[node.zPosition] = list
            return accumulator
        }
    }
}

Test

class Foo: SKNode {
    let num: Int

    init(num: Int) {
        self.num = num
        super.init()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override var description: String { return num.description }
}

let scene = SKScene()
let node0 = Foo(num: 0)
node0.zPosition = 1
let node1 = Foo(num: 1)
let node2 = Foo(num: 2)
node2.zPosition = 1
let node3 = Foo(num: 3)
let node4 = Foo(num: 4)

scene.addChild(node0)
scene.addChild(node1)
scene.addChild(node2)
scene.addChild(node3)
scene.addChild(node4)

Now you can group the children by zPosition

let dict = scene.childrenByZPosition()
dict[0] // [1, 3, 4]
dict[1] // [0, 2]