Search code examples
swiftfunctionloopssprite-kittouchesbegan

Remove a function from SKScene when Touches Begin


I have a blue sky texture moving from the top of the screen to the bottom, repeating forever in a function. However, when touches begin, I would like the blue sky to completely fade out after a duration, then completely remove from the scene.

I am able to get the sky to fade out momentarily, then it seems as though half of the loop is removed, but I still get the sky coming down every other time. Here's a video of the problem: Blue Sky Video

In the video, touches begin when the pause button appears at the top left of the screen - before touches begin, the blue sky moves from top to bottom seamlessly as it should.

FUNCTION

func createBlueSky() {
    let blueSkyTexture = SKTexture(imageNamed: "blueSky")

    for i in 0 ... 1 {
        let blueSky = SKSpriteNode(texture: blueSkyTexture)
        blueSky.name = "blueSky"
        blueSky.zPosition = -60
        blueSky.anchorPoint = CGPoint.zero
        blueSky.position = CGPoint(x: 0, y: (blueSkyTexture.size().height * CGFloat(i)))
        worldNode.addChild(blueSky)

        let moveDown = SKAction.moveBy(x: 0, y: -blueSkyTexture.size().height, duration: 10)
        let moveReset = SKAction.moveBy(x: 0, y: blueSkyTexture.size().height, duration: 0)
        let moveLoop = SKAction.sequence([moveDown, moveReset])
        let moveForever = SKAction.repeatForever(moveLoop)
        blueSky.run(moveForever)
        }

}

I've added the above function to didMove(toView)

override func didMove

createBlueSky()

Then in my touches began I added this code to fade out and remove from parent.

I saw in another post that to access the blue sky from another function, I'd need to give it a name, which I did. Still no luck :/

override func touchesBegan

let blueSky =  worldNode.childNode(withName: "blueSky") as! SKSpriteNode
    let blueSkyFade = SKAction.fadeOut(withDuration: 3)
    let blueSkyFadeWait = SKAction.wait(forDuration: 3)
    let removeBlueSky = SKAction.removeFromParent()
    blueSky.run(SKAction.sequence([blueSkyFadeWait, blueSkyFade, removeBlueSky]))

I'm very new to Swift, but I hope the question was specific enough. I'm happy to provide any other necessary information.


Solution

  • You are creating 2 blueSky nodes, but you only fade and remove 1 of them. You need to enumerate through all of the nodes with the name you are looking for. To do this, you call enumerateChildNodes(withName:}

    let blueSkyFade = SKAction.fadeOut(withDuration: 3)
    let blueSkyFadeWait = SKAction.wait(forDuration: 3)
    let removeBlueSky = SKAction.removeFromParent()
    enumerateChleNodes(withName:"blueSky")
    {
        (blueSky,stop) in 
        blueSky.run(SKAction.sequence([blueSkyFadeWait, blueSkyFade, removeBlueSky]))
    }