William Tong
William Tong

Reputation: 475

"Attemped to add a SKNode which already has a parent:" in Repeat Loop. Any simple work around?

I am pretty Newbie to programming. And I am trying to pile up the random blocks dynamically till it hits the upper frame. But it seems that Swift doesn't let me to do so. Did I miss anything please? Any input are appreciated.

let blocks =[block1,block2,block3,block4,block5,block6,block7,block8,block9,block10,block11,block12]


    var block:SKSpriteNode!

    let blockX:Double = 0.0
    var blockY:Double = -(self.size.height/2)

    repeat{
        block = blocks.randomBlock()
        block.zPosition = 2
        block.position = CGPoint(x:blockX, y:blockY)


        block.size.height = 50
        block.size.width = 50
        self.addChild(block)

        blockY += 50


    } while( block.position.y < self.size.height)

extension Array { 
    func randomBlock()-> Element { 
       let randint = Int(arc4random_uniform(UInt32(self.count))) 
       return self[randint] 
    } 
}

Upvotes: 1

Views: 31

Answers (1)

Ron Myschuk
Ron Myschuk

Reputation: 6061

you need to have someway of tracking which blocks have been selected and ensure that they don't get selected again. The method below uses an array to store the indexes of selected blocks and then uses recursion to find a cycle through until an unused match is found.

private var usedBlocks = [Int]()

func randomBlock() -> Int {

    guard usedBlocks.count != blocks.count else { return -1 }

    let random = Int(arc4random_uniform(UInt32(blocks.count)))

    if usedBlocks.contains(random) {
        return randomBlock()
    }
    usedBlocks.append(random)

    return random
}

in your loop change your initializer to

let index = randomBlock()

if index > -1 {
    block = blocks[index]
    block.zPosition = 2
    block.position = CGPoint(x:blockX, y:blockY)
}

remember that if you restart the game or start a new level, etc. you must clear all of the objects from usedBlocks

usedBlocks.removeAll()

Upvotes: 1

Related Questions