2
votes

There are 3 SKSpriteNode in my SKScene Class. One of them is player and the other ones are gold and unvisible finish object such as when player touch it, game is finished. My problem is that when player collide the gold, his gold budget should increase just 50 gold. However, Xcode detect multiple collision and gold budget increasing multiple times. 50-60 collision is detected instead of one collision. I researched how to solve this problem. I found that I should use Bool, I tried to set bool but it didn't solve my problem. Is there anyone can help me about how to detect just one collision? Here is the my GameScene class codes :

import SpriteKit
import GameplayKit

class level3: SKScene, SKPhysicsContactDelegate {

    let playerFileName = "player"
    let starFileName = "50Gold"
    let goalFileName = "goal"
    let playerCategory   : UInt32 = 0x1 << 1
    let goalCategory : UInt32 = 0x1 << 2
    let starCategory : UInt32 = 0x1 << 3

    override func didMove(to view: SKView) {
        super.didMove(to: view)
        physicsWorld.contactDelegate = self

        let goal = childNode(withName: goalFileName) as! SKSpriteNode
        let player = childNode(withName: playerFileName) as! SKSpriteNode
        let star = childNode(withName: starFileName) as! SKSpriteNode

        player.physicsBody!.categoryBitMask = playerCategory
        goal.physicsBody!.categoryBitMask = goalCategory

        star.physicsBody?.collisionBitMask = 1
        player.physicsBody?.collisionBitMask = 1
        goal.physicsBody?.collisionBitMask = 1
        goal.physicsBody?.isDynamic = true

        goal.physicsBody!.contactTestBitMask = playerCategory

        player.physicsBody?.isDynamic = true
        star.physicsBody?.isDynamic = true
        player.physicsBody?.contactTestBitMask = starCategory

        star.physicsBody?.categoryBitMask = starCategory

        func didBegin(_ contact: SKPhysicsContact) {

            // 1
            var firstBody: SKPhysicsBody
            var secondBody: SKPhysicsBody
            // 2
            if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
                firstBody = contact.bodyA
                secondBody = contact.bodyB
            } else {
                firstBody = contact.bodyB
                secondBody = contact.bodyA
            }

            if firstBody.categoryBitMask == playerCategory && secondBody.categoryBitMask == goalCategory {

                contact.bodyB.node?.removeFromParent()

            }

            if firstBody.categoryBitMask == playerCategory && secondBody.categoryBitMask == starCategory {

                PlaySceneViewController.instance.gold += 50
                print(PlaySceneViewController.instance.gold)

                contact.bodyB.node?.removeFromParent()

            }

        }
    }
}
1
removing Xcode tag and reference in the title as this is a problem you're having implementing something with SpriteKit, not a problem with he Xcode IDEMichael Dautermann
Check my answer to a very similar question here: stackoverflow.com/a/44384390/1430420Steve Ives

1 Answers

0
votes

Yep - this happens. The way to handle it (you can't get sprite-kit to NOT call didBegin multiple times in some circumstances) is to make sure that your contact code accommodates this and that handling the contract multiple times does not cause a problem (such as adding to the score multiple times, removing multiple lives, trying to access a node or physicsBody that has been removed etc).

For more detail and possible solutions, see this answer : https://stackoverflow.com/a/44384390/1430420