1
votes

I have a question as to why my SpriteKit nodes are not being removed from my parent node in the code below.

My project is currently in two parts, one is the GameScene class which comes default when you build a SpriteKit project, and the other is a Circles class which I made to operate on each circle in the game.

The circles are stored in an array here:

var circlesInPlay = [Circles]()

Basically, I'm trying to design a simple game where circles decrease in size, and when they are of 0 width, are removed from the screen.

My code to do this is here, in the

override func update(currentTime: CFTimeInterval) {


    timeSinceUpdate = timeSinceUpdate + 1
    print("time since update: " + String(timeSinceUpdate))

    if timeForUpdate == timeSinceUpdate {
        newCircle()
        timeSinceUpdate = 0
        //timeForUpdate = Int(arc4random_uniform(100) + 1)
        timeForUpdate = 100
    }

    //Check to see if circle transparancies are 0

    if checkGameOver() {

        gameOver()
    }

    updateCircles()
    removeCircles()

The timeSinceUpdate variable is the time since the last circle has been placed onto the screen, which increases by one for every frame updated.

updateCircles() calls this,

func updateCircles() {

    for c in circlesInPlay {

        c.update()

    }

}

Which calls update() in the Circles class I made in another swift file:

    func update() {

    transparancy = transparancy - transparancyDecrease
    size = size - ds

    if (size <= 0) {
        node.removeFromParent()
    }

    node.size.height = size
    node.size.width = size

}

The other call from the update function to removeCircles() is here

func removeCircles() {

    var posn = circlesInPlay.count - 1

    for c in circlesInPlay {

        if (c.size < 0) {

            c.produceNode().removeFromParent()
            circlesInPlay.removeAtIndex(posn)
            posn = posn - 1

        }

    }

}

What i'm really getting at is I have no idea why the circles are sometimes getting stuck or not being removed from the screen.

Any help is greatly appreciated!

The entire game code is as follows:

import SpriteKit

class GameScene: SKScene {

    var bgImage = SKSpriteNode(imageNamed: "background.png")

    let screenSize = UIScreen.mainScreen().bounds

    var timeSinceUpdate: Int = 0

    var circlesInPlay = [Circles]()

    var timeForUpdate = Int(arc4random_uniform(200) + 1)

    override func didMoveToView(view: SKView) {

        bgImage.position = CGPointMake(self.size.width/2, self.size.height/2)
        bgImage.zPosition = -100
        self.addChild(bgImage)






    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
       /* Called when a touch begins */

        for touch in touches {
            let location = touch.locationInNode(self)

            if !isTouchInCircle(location) {

                gameOver()
            }


        }
    }

    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */

        timeSinceUpdate = timeSinceUpdate + 1
        print("time since update: " + String(timeSinceUpdate))

        if timeForUpdate == timeSinceUpdate {
            newCircle()
            timeSinceUpdate = 0
            //timeForUpdate = Int(arc4random_uniform(100) + 1)
            timeForUpdate = 100
        }

        //Check to see if circle transparancies are 0

        if checkGameOver() {

            gameOver()
        }

        updateCircles()
        removeCircles()

    }

    func newCircle(){

        let sizeX = UInt32(CGRectGetMaxX(self.frame))
        let randomx = CGFloat(arc4random_uniform(sizeX))

        let sizeY = UInt32(CGRectGetMaxY(self.frame))
        let randomy = CGFloat(arc4random_uniform(sizeY))

        //let randomx = CGFloat(arc4random_uniform(UInt32(self.size.width)))
        //let randomy = CGFloat(arc4random_uniform(UInt32(self.size.height)))

        if (circlesInPlay.count < 5) {

            circlesInPlay.append(Circles.init(x: randomx, y: randomy))
            self.addChild((circlesInPlay[circlesInPlay.count - 1]).produceNode())
        }

    }

    func checkGameOver() -> Bool {


        for c in circlesInPlay {

            if c.getTransparancy() == 0 {

                return false

            }

        }

        return true
    }

    func isTouchInCircle(touch: CGPoint) -> Bool {

        for c in circlesInPlay {

            if (c.getX() <= (touch.x * 1.10)) {

                return true
            }

        }

        return false

    }


    func updateCircles() {

        for c in circlesInPlay {

            c.update()

        }

    }

    func removeCircles() {

        var posn = circlesInPlay.count - 1

        for c in circlesInPlay {

            if (c.size < 0) {

                c.produceNode().removeFromParent()
                circlesInPlay.removeAtIndex(posn)
                posn = posn - 1

            }

        }

    }


    func gameOver() {


    }

}



import Foundation
import SpriteKit
import GameKit


class Circles {


    var node = SKSpriteNode()

    var size: CGFloat = 200
    var ds: CGFloat = 2

    var colorC: String;


    var xpos: CGFloat
    var ypos: CGFloat

    var transparancy: Int
    var transparancyDecrease: Int = 1



    let arrayColors = ["circleRed.png", "circleBlue.png", "circlePink.png", "circleGreen.png", "circleYellow.png"]


    //The innitial constructor
    init(x: CGFloat, y: CGFloat) {

        self.xpos = x
        self.ypos = y

        self.transparancy = 100

        let randomIndex = Int(arc4random_uniform(UInt32(arrayColors.count)))

        colorC = arrayColors[randomIndex]

        node.texture = SKTexture(imageNamed: colorC)
        node.position = CGPointMake(self.xpos, self.ypos)
        node.size.height = self.size
        node.size.width = self.size

    }

    func produceNode() -> SKSpriteNode {

        return node

    }


    func setColor() {

        let randomIndex = Int(arc4random_uniform(UInt32(arrayColors.count)))

        colorC = arrayColors[randomIndex]



    }


    func update() {

        transparancy = transparancy - transparancyDecrease
        size = size - ds

        if (size <= 0) {
            node.removeFromParent()
        }

        node.size.height = size
        node.size.width = size

    }

    func getX() -> CGFloat {

        return xpos
    }

    func getY() -> CGFloat {

        return ypos
    }


    /*
    func getColor() -> SKColor {

        return colorC

    }*/

    func getTransparancy() -> Int {

        return transparancy

    }

}
1
In removeCircles() method you want if c.size <= 0 {...} instead of c.size < 0.Whirlwind

1 Answers

1
votes

The issue is in this snippet:

        var posn = circlesInPlay.count - 1

    for c in circlesInPlay {

        if (c.size < 0) {

            c.produceNode().removeFromParent()
            circlesInPlay.removeAtIndex(posn)
            posn = posn - 1

        }

    }

You are always removing the last element from you collection and not the element which you are using in the iteration. Also be careful when you are changing the collection while iterating thrue it. The indexes will change, if you remove elements from the collection.