Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

swift - Physics detecting collision multiple times

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...