简体   繁体   中英

collision detection not working fully

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM