Hamzah Qadri
Hamzah Qadri

Reputation: 1

sprite not being removed with SKAction

I am trying clouds move up and spawn but I keep getting

'terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attemped to add a SKNode which already has a parent: name:'(null)' texture:[ 'CLOUD' (746 x 497)] position:{198.66667175292969, 1227.987060546875} scale:{0.30, 0.30} size:{223.80000305175781, 149.10000610351562} anchor:{0.5, 0.5} rotation:0.00'. '

I'm not sure what's going wrong any help would be much appreciated

 let cloud1 = SKSpriteNode(imageNamed: "CLOUD")
 let cloud2 = SKSpriteNode(imageNamed: "CLOUD")

class GameScene: SKScene {

override func didMove(to view: SKView) {
          self.anchorPoint = CGPoint(x: 0.5, y: 0.5)
 setUp()
}

func setUp() {

    let block = SKAction.run ({
        self.spawnClouds()

        if (cloud1.position.y  > self.size.height) {

        cloud1.removeFromParent()
            cloud2.removeFromParent()
        }
    })

    let wait = SKAction.wait(forDuration: 9)

    let action = SKAction.repeat(block, count: 10)
            let removes = SKAction.removeFromParent()

    let sequence = SKAction.sequence([block, wait, action, removes])

    self.run(sequence)
}

@objc func spawnClouds() {
    let gapHeight = self.frame.width / 9
    let movementAmount = arc4random() % UInt32(self.frame.width / 2)
    let cloudOffset = CGFloat(movementAmount) - self.frame.width / 4

   // let cloud1 = SKSpriteNode(imageNamed: "CLOUD")

    cloud1.xScale = 0.3
    cloud1.yScale = 0.3
    cloud1.zPosition = 1
    self.addChild(cloud2)
    cloud2.xScale = 0.3
    cloud2.yScale = 0.3
    cloud2.zPosition = 1

    cloud1.position = CGPoint(x:self.frame.minX / 2 + gapHeight / 5 + cloudOffset , y: self.frame.minY  )
    cloud2.position = CGPoint(x:self.frame.maxX / 2 + gapHeight / 5 + cloudOffset , y: self.frame.minY  )

    self.addChild(cloud1)

    var distanceToMove = CGFloat(self.frame.size.width + 2.0 * cloud1.frame.width)
    let moveCloud = SKAction.move(by: CGVector(dx:0, dy:25 * self.frame.width), duration: TimeInterval(self.frame.height / 15 ))

    let newaction = SKAction.removeFromParent()
    let new = SKAction.sequence([moveCloud, newaction])

    cloud1.run(new)
    cloud2.run(new)
}

override func update(_ currentTime: TimeInterval) {

    if cloud2.position.y > size .height {

        cloud1.removeFromParent()
        cloud2.removeFromParent()
    }
    }

}

Upvotes: 0

Views: 36

Answers (2)

Steve Ives
Steve Ives

Reputation: 8134

cloud1 and cloud2 are properties i.e. visible everywhere. So when you do addChild(cloud1) and addChild(cloud2) these are not newly create sprites but are the same ones you've added before, hence the message 'Attempting to add an SKNode that already has a parent'

In a function that is designed to spawn nodes, you usually create a new SKNode to spawn each time, just like your line of code that is commented out:

// let cloud1 = SKSpriteNode(imageNamed: "CLOUD")

This will make sure that cloud1 is a new node each time.

You should also be doing this for cloud2.

Upvotes: 1

E.Coms
E.Coms

Reputation: 11531

Two things, the first is action should be a sequence.

   // let action = SKAction.repeat( block, count: 10)
     let action = SKAction.repeat( SKAction.sequence( [block,wait]), count: 10)

second ,the timing should be perfect around 9s, i.e. self.frame.height / 15

   //let moveCloud = SKAction.move(by: CGVector(dx:0, dy:25 * self.frame.width), duration: TimeInterval(self.frame.height / 15 ))

so this could be :

  let moveCloud = SKAction.move(by: CGVector(dx:0, dy:2.5 * self.frame.width), duration: TimeInterval(self.frame.height / 150 ))

Upvotes: 0

Related Questions