2
votes

When the ball collides with the cup, the score should increase by 1. However it currently increases by 1, 3 or sometimes 4 which means the collision is being detected multiple times.

I think I must be checking for collisions incorrectly:

let ballCategory   : UInt32 = 0x1 << 0 
let cupCategory : UInt32 = 0x1 << 1 

And in my didMoveToView:

//Set physicsBody of scene to a physics body that borders the screen

self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
physicsWorld.contactDelegate = self

//Ball
ballSprite.physicsBody = SKPhysicsBody(rectangleOfSize: ballSprite.size)
ballSprite.physicsBody!.categoryBitMask = ballCategory
ballSprite.physicsBody!.contactTestBitMask = cupCategory

//Cup
cupSprite.physicsBody = SKPhysicsBody(edgeLoopFromRect: cupSprite.size) 
cupSprite.physicsBody!.categoryBitMask = cupCategory
cupSprite.physicsBody!.contactTestBitMask = ballCategory

In my didBeginContact:

var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody

//Assign the two physics bodies so that the one with the lower category is always stored in firstBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {

    firstBody = contact.bodyA
    secondBody = contact.bodyB
} 
else {

    firstBody = contact.bodyB
    secondBody = contact.bodyA
}

//contact between ball and cup
if firstBody.categoryBitMask == ballCategory && secondBody.categoryBitMask == cupCategory {

    score++
    println("point scored")
    moveBall() //Move ball back to start position
}

This works in the sense that it is detecting the collision, however it is happening multiple times whereas it should only happen once.

2
Make sure you have fully separate object categories.Alex Bailey

2 Answers

2
votes

You can set one BOOL value to check if is allowed contact handling(set YES at the beginning). After updating score, you can set that variable to NO, then run moveBall() to start again and at the end of moveBall() method set BOOL value to YES. I think something like that should work.

Other way would be to remove ball/or cup nodes from parent and set it to nil (and then re-recreate them). Also I don't know how much SpriteKit "likes" this way(removing nodes before physics simulation is done).

Third way would be to have Ball class with some BOOL property that indicating whether the ball should be moved to start position. Based on that value you should update the score variable/handle contacts and collisions. So after updating the score, you set BOOL value to YES and then run moveBall() and then set BOOL value to NO etc...Similar as first method I described.

-1
votes

this happened to me, what to do is simple, just define everything like this each node needs one: first make this for the nodes, either if its a screen border or what ever node it hits, say this:

let nodesCatergory : UInt32 = 0x1 << 1 

after, put this nodesCatergory to everynode you have in game, or the nodes that it collides with, then add it like this:

if firstBody.categoryBitMask == ballCategory &&       secondBody.categoryBitMask == nodesCatergory {
//score++
println("point scored, NOT!")
//moveBall() //Move ball back to start position
  }

thats it! you can do these till the desired effect is acquired!