2
votes

I am building an iOS swift game with collision. The hero is being bombarded by small stars coming from the right side of the screen. Every time a star hits the hero, the score is iterated and the star is removed. But, more than one point is added to the score.

Node Set-up:

var star = SKSpriteNode(imageNamed: "star")
star.size = CGSizeMake(30, 30)
star.zPosition = 10
var starPhysicsRect = CGRectMake(star.position.x - star.frame.size.width / 2, star.position.y - star.frame.size.width / 2, star.frame.size.width, star.frame.size.height)
star.physicsBody = SKPhysicsBody(edgeLoopFromRect: starPhysicsRect)
star.physicsBody?.restitution = 0
star.name = "star"
star.physicsBody?.mass = 0
return star

didBeginContact Function:

func didBeginContact(contact: SKPhysicsContact) {
    //collision variables
    var firstBodyNode = contact.bodyA.node as! SKSpriteNode
    var secondBodyNode = contact.bodyB.node as! SKSpriteNode
    var firstNodeName = firstBodyNode.name
    var secondNodeName = secondBodyNode.name

    //other variables
    var scoreLabel: SKLabelNode = constantsInstance.scoreLabel(position: CGPointMake(self.frame.size.width * 0.86, self.frame.size.height * 0.928))


    //check if hero hit star
    if firstNodeName == "hero" && secondNodeName == "star" {
        println("star hit")
        secondBodyNode.removeFromParent()

        //iterate score
        childNodeWithName("scoreLabel")?.removeFromParent()
        scoreLabel.text = "\(counterForScore)"
        counterForScore++
        self.addChild(scoreLabel)
    }
}

I get "star hit" printed to the console several times as well. Why would the didBeginContact function be called more than once if I remove the star on the first call of the function?

I have run simulations on a smaller scale and found that the star goes fairly deep into the hero (because of the SKAction), if there is no remove command. Could it be that the didBeginContact function is called many times while the star is going into the hero and before it is removed?

All help is greatly appreciated.

2
Could you please show us the code where you set up your spriteNodes? - T. Benjamin Larsen
Just added the setup - Michael Berk
Thanks! Seems there are something amiss here? star.name = "bottomStar" yet triggers when you check secondName == "star" ? Are you perhaps looking at a different interaction alltogether? - T. Benjamin Larsen
Good catch. I missed that when I was adapting my code. Sorry for the sloppy error. Just changed it back. - Michael Berk
OK, a couple of other questions: any changes made to the sprite elsewhere? Are you just creating a single instance of the starSprite? - T. Benjamin Larsen

2 Answers

3
votes

You can check if parent of the SKSpriteNode is nil before continuing.

func didBeginContact(contact: SKPhysicsContact) {
    var firstBodyNode : SKSpriteNode!
    var secondBodyNode : SKSpriteNode!

    //  Assuming that the contact test bit mask of star is greater than hero. If it's not you should reverse the condition.

    if contact.bodyA.contactTestBitMask < contact.bodyB.contactTestBitMask {
        firstBodyNode = contact.bodyA.node as! SKSpriteNode
        secondBodyNode = contact.bodyB.node as! SKSpriteNode
    } else {
        firstBodyNode = contact.bodyB.node as! SKSpriteNode
        secondBodyNode = contact.bodyA.node as! SKSpriteNode
    }

    var firstNodeName = firstBodyNode.name
    var secondNodeName = secondBodyNode.name

    if firstNodeName == "hero" && secondNodeName == "star" {
        if secondBodyNode.parent != nil {
           // Your code.
        }
    }
}
1
votes

Could it possibly be due to the physicsBody:

var star = SKSpriteNode(imageNamed: "star")
star.size = CGSizeMake(30, 30)
star.zPosition = 10
var starPhysicsRect = CGRectMake(star.position.x - star.frame.size.width / 2, star.position.y - star.frame.size.width / 2, star.frame.size.width, star.frame.size.height)
star.physicsBody = SKPhysicsBody(edgeLoopFromRect: starPhysicsRect)

Have a look at the logic creating the starPhysicsRect:

(star.position.x - star.frame.size.width / 2, star.position.y - star.frame.size.width / 2, star.frame.size.width, star.frame.size.height)

From what I can see this translates to the following values: (-15, -15, 30, 30) those negative position-coordinates seem odd. Are you sure you don't just want: SKPhysicsBody(rectangleOfSize: star.size) ?