Search code examples
swiftxcodesprite-kitsknode

How to refer to multiple SKNodes at once in SpriteKit?


In order to prevent a lot of the same code, I want to refer to every single node(all children of the same parent) on the scene with one call. I have a gate at the bottom of the scene and I want to detect if any node(many different nodes getting added to the scene) passes the y position of this gate.

This is how my update function looks now:

override func update(_ currentTime: TimeInterval) {
// code I want to simplify

    if Cap.position.y < illustration2.position.y 
    || Cap2.position.y < illustration2.position.y 
    || Cap3.position.y < illustration2.position.y 
    || Cap4.position.y < illustration2.position.y 
    || Cap5.position.y < illustration2.position.y  
    || Cap6.position.y < illustration2.position.y 
    || Cap7.position.y < illustration2.position.y 
    || Cap8.position.y < illustration2.position.y 
    || Cap9.position.y < illustration2.position.y 
    || Cap10.position.y < illustration2.position.y {


     // Transitioning to game over

        let transition = SKTransition.crossFade(withDuration: 0)
        let gameScene = GameOver(size: self.size)
        self.view?.presentScene(gameScene, transition: transition)
}

}

All Caps are children of illustration2, so I was thinking about something like:

//if the y position of any child is below the illustration2 y position the game over scene starts

if dontaiIllustration2.children.position.y < dontaiIllustration2.position.y {

        }

Or another approach could be to check that the illustration2 node has the lowest y position from all nodes at the scene.


Solution

  • You can’t. You need to place them into a collection (array, dictionary, set, etc) and then find a way to traverse through them with something like foreach, map, compactMap (formally flatMap), reduced, etc. in your case, I would use reduce.

    let caps = [Cap1,Cap2,Cap3,Cap4,Cap5,Cap6,Cap7,Cap8,Cap9,Cap10]
    let result = caps.reduce(false,{value,cap in return value || cap.position.y < illustration2.position.y})
    if result {
        // Transitioning to game over
    
        let transition = SKTransition.crossFade(withDuration: 0)
        let gameScene = GameOver(size: self.size)
        self.view?.presentScene(gameScene, transition: transition)
    }
    

    What this is doing, is going through each of your nodes, and evaluating the current equation with the previous result.

    So we start at a false, then it will check if cap y > illustration y. If true, then our value becomes true, and this value carries over to the next cap. It repeats this until you run out of caps, and then returns the final value, which will be a false or a true.