Why is there multiple collision calls Sprite Kit S

2019-05-28 05:16发布

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条回答
看我几分像从前
2楼-- · 2019-05-28 05:47

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) ?

查看更多
\"骚年 ilove
3楼-- · 2019-05-28 05:54

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.
        }
    }
}
查看更多
登录 后发表回答