import SpriteKit
import GameplayKit
class GameScene: SKScene, SKPhysicsContactDelegate {
let balls = [
SKSpriteNode(imageNamed: "blueball.png"),
SKSpriteNode(imageNamed: "greenball.png"),
SKSpriteNode(imageNamed: "realredball.png"),
]
let redRectangle = SKSpriteNode(imageNamed: "redrectangle.png")
let blueRectangle = SKSpriteNode(imageNamed: "bluerectangle.png")
let greenRectangle = SKSpriteNode(imageNamed: "greenrectangle.png")
let blueBallCategory :UInt32 = 0x1 << 0
let greenBallCategory :UInt32 = 0x1 << 1
let realRedBallCategory :UInt32 = 0x1 << 2
let redRectangleCategory : UInt32 = 0x1 << 3
let blueRectangleCategory : UInt32 = 0x1 << 4
let greenRectangleCategory : UInt32 = 0x1 << 5
override func didMove(to view: SKView) {
spawnBallsandRectangles()
physicsWorld.contactDelegate = self
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
physics()
}
func didBegin(_ contact: SKPhysicsContact) {
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
if firstBody.categoryBitMask == blueBallCategory && secondBody.categoryBitMask == blueRectangleCategory {
print("alive")
}
else if firstBody.categoryBitMask == greenBallCategory && secondBody.categoryBitMask == greenRectangleCategory {
print("alive")
}
else if firstBody.categoryBitMask == realRedBallCategory && secondBody.categoryBitMask == redRectangleCategory {
print("alive")
}
else if firstBody.categoryBitMask == blueBallCategory || firstBody.categoryBitMask == greenBallCategory && secondBody.categoryBitMask == redRectangleCategory{
print("dead")
}
else if firstBody.categoryBitMask == realRedBallCategory || firstBody.categoryBitMask == greenBallCategory && secondBody.categoryBitMask == blueRectangleCategory {
print("dead")
}
else if firstBody.categoryBitMask == realRedBallCategory || firstBody.categoryBitMask == blueBallCategory && secondBody.categoryBitMask == greenBallCategory {
print("dead")
}
}
func spawnBallsandRectangles() {
let ball = balls[Int(arc4random_uniform(UInt32(balls.count)))]
ball.position = CGPoint(x: -200, y: 250)
ball.size = CGSize(width: 70, height: 70)
redRectangle.position = CGPoint(x: 0, y: -600)
redRectangle.size = CGSize(width: 200, height: 20)
blueRectangle.position = CGPoint(x: -200, y: -600)
blueRectangle.size = CGSize(width: 200, height: 20)
greenRectangle.position = CGPoint(x: 200, y: -600)
greenRectangle.size = CGSize(width: 200, height: 20)
self.addChild(ball)
self.addChild(redRectangle)
self.addChild(blueRectangle)
self.addChild(greenRectangle)
}
func physics(){
for ball in balls{
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height/2)
}
redRectangle.physicsBody = SKPhysicsBody(rectangleOf: redRectangle.size)
redRectangle.physicsBody?.affectedByGravity = false
redRectangle.physicsBody?.isDynamic = false
blueRectangle.physicsBody = SKPhysicsBody(rectangleOf: redRectangle.size)
blueRectangle.physicsBody?.affectedByGravity = false
blueRectangle.physicsBody?.isDynamic = false
greenRectangle.physicsBody = SKPhysicsBody(rectangleOf: redRectangle.size)
greenRectangle.physicsBody?.isDynamic = false
greenRectangle.physicsBody?.affectedByGravity = false
balls[0].physicsBody?.categoryBitMask = blueBallCategory
balls[1].physicsBody?.categoryBitMask = greenBallCategory
balls[2].physicsBody?.categoryBitMask = realRedBallCategory
balls[0].physicsBody?.contactTestBitMask = redRectangleCategory
balls[1].physicsBody?.contactTestBitMask = redRectangleCategory
balls[1].physicsBody?.contactTestBitMask = blueRectangleCategory
balls[2].physicsBody?.contactTestBitMask = blueRectangleCategory
balls[0].physicsBody?.contactTestBitMask = greenRectangleCategory
balls[2].physicsBody?.contactTestBitMask = greenRectangleCategory
balls[0].physicsBody?.contactTestBitMask = blueRectangleCategory
balls[1].physicsBody?.contactTestBitMask = greenRectangleCategory
balls[2].physicsBody?.contactTestBitMask = redRectangleCategory
redRectangle.physicsBody?.categoryBitMask = redRectangleCategory
blueRectangle.physicsBody?.categoryBitMask = blueRectangleCategory
greenRectangle.physicsBody?.categoryBitMask = greenRectangleCategory
}
}
I have set up collision detection so that if a ball collides into a rectangle that match colors, the program prints ("alive"). And the program is supposed to print ("dead") if the colors don't match. It detects collision if the colors match and it prints ("alive") but it doesn't print ("dead"). Could someone please help ,thanks.
You might find that structuring your didBegin()
like this might help to get rid of all those else if
s:
func didBegin(_ contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case blueBallCategory | blueRectangleCategory:
print("Alive! Blue ball has hit blue rectangle.")
case greenBallCategory | greenRectangleCategory:
print("Alive! Green ball has hit green rectangle.")
case redBallCategory | redRectangleCategory:
print("Alive! Red ball has hit red rectangle.")
default :
print("Dead! Some other contact has occurred")
}
}
What do you want to happen if a ball hits a rectangle of a different colour?
EDIT:
From this code in your physics()
function:
balls[0].physicsBody?.contactTestBitMask = redRectangleCategory
balls[1].physicsBody?.contactTestBitMask = redRectangleCategory
balls[1].physicsBody?.contactTestBitMask = blueRectangleCategory
balls[2].physicsBody?.contactTestBitMask = blueRectangleCategory
balls[0].physicsBody?.contactTestBitMask = greenRectangleCategory
balls[2].physicsBody?.contactTestBitMask = greenRectangleCategory
balls[0].physicsBody?.contactTestBitMask = blueRectangleCategory
balls[1].physicsBody?.contactTestBitMask = greenRectangleCategory
balls[2].physicsBody?.contactTestBitMask = redRectangleCategory
each time you assign a new value to the contactTestbitMask for a specific physics body, you are overwriting the previous value, not adding to it. Thus the only lines that matter are:
balls[0].physicsBody?.contactTestBitMask = blueRectangleCategory
balls[1].physicsBody?.contactTestBitMask = greenRectangleCategory
balls[2].physicsBody?.contactTestBitMask = redRectangleCategory
So balls[0] (blue ball) only contacts blue rectangles, balls[1] (green ball) only contacts green rectangles and balls[2] (real red ball) only contacts red rectangles. So didBegin()
will not be called if a ball contacts a rectangle of a different colour, which is why you never see your 'dead' message.
Another Edit:
If you want all balls to trigger didBegin() when then contact any rectangle, then your contactTestBitMasks
for the balls should include ALL the rectangles:
for ball in balls {
balls.physicsBody?.contactTestBitMask = blueRectangleCategory | greenRectangleCategory | redRectangleCategory
}
or if the balls already have some contacts defined and you just want to add the rectangles to their collision bit masks:
for ball in balls {
balls.physicsBody?.contactTestBitMask |= (blueRectangleCategory | greenRectangleCategory | redRectangleCategory)
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.