спрайт не удаляется с помощью SKAction

#ios #swift #sprite-kit #skaction

#iOS #swift #sprite-kit #skaction

Вопрос:

Я пытаюсь облака перемещаться вверх и появляться, но я продолжаю получать

«завершение работы приложения из-за неперехваченного исключения NSInvalidArgumentException», причина: «Предпринята попытка добавить SKNode, у которого уже есть родительский: имя:'(null)’ текстура: [ ‘CLOUD’ (746 x 497)] позиция: {198.66667175292969, 1227.987060546875} масштаб: {0.30, 0.30} размер: {223.80000305175781, 149.10000610351562} привязка: {0.5, 0.5} вращение: 0.00′. ‘

Я не уверен, что происходит не так, любая помощь была бы высоко оценена

  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()
    }
    }
  

}

Комментарии:

1. Это очень плохой способ представления кода и просьбы неоплачиваемого добровольца взглянуть.

Ответ №1:

cloud1 и cloud2 являются свойствами, то есть видны везде. Поэтому, когда вы это делаете, addChild(cloud1) и addChild(cloud2) это не вновь созданные спрайты, а те же самые, которые вы добавляли ранее, отсюда и сообщение «Попытка добавить SKNode, у которого уже есть родительский»

В функции, которая предназначена для создания узлов, вы обычно создаете новый SKNode, который будет появляться каждый раз, точно так же, как ваша строка кода, которая закомментирована:

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

Это гарантирует, что cloud1 каждый раз является новым узлом.

Вы также должны делать это для cloud2.

Ответ №2:

Две вещи, первая — действие должно быть последовательностью.

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

во-вторых, время должно быть идеальным около 9 секунд, т. Е. self.frame.height / 15

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

так что это может быть :

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