简体   繁体   中英

Collision detection interrupting another collision detection - Swift

As of now, I have an SKSpriteNode that detects collisions with my ball and increments my score by + 1 when they collide. Also in the collision is the code that detects if my ball hits a wall.

    let scoreNode = SKSpriteNode()

    scoreNode.size = CGSize(width: 750, height: 10)
    scoreNode.position = CGPoint(x: self.frame.width / 2, y: self.frame.height / 2 + 100)
    scoreNode.physicsBody = SKPhysicsBody(rectangleOfSize: scoreNode.size)
    scoreNode.physicsBody?.affectedByGravity = false
    scoreNode.physicsBody?.dynamic = true
    scoreNode.physicsBody?.categoryBitMask = PhysicsCat.Score
    scoreNode.physicsBody?.collisionBitMask = 0
    scoreNode.physicsBody?.contactTestBitMask = PhysicsCat.Ball
    scoreNode.color = SKColor.clearColor()

func didBeginContact(contact: SKPhysicsContact) {


    let firstBody = contact.bodyA
    let secondBody = contact.bodyB



    if firstBody.categoryBitMask == PhysicsCat.Score && secondBody.categoryBitMask == PhysicsCat.Ball{

        score += 1
        scoreLbl.text = "\(score)"
        firstBody.node?.removeFromParent()


    }

    else if firstBody.categoryBitMask == PhysicsCat.Ball && secondBody.categoryBitMask == PhysicsCat.Score {

        score += 1
        scoreLbl.text = "\(score)"
        secondBody.node?.removeFromParent()


    }
    else if firstBody.categoryBitMask == PhysicsCat.Ball && secondBody.categoryBitMask == PhysicsCat.Wall || firstBody.categoryBitMask == PhysicsCat.Wall && secondBody.categoryBitMask == PhysicsCat.Ball{

        enumerateChildNodesWithName("wallPair", usingBlock: ({
            (node, error) in

            node.speed = 0
            self.removeAllActions()

        }))

        if died == false{
            died = true
            createBTN()
            fallDie()
        }
    }

    else if firstBody.categoryBitMask == PhysicsCat.Ball && secondBody.categoryBitMask == PhysicsCat.Wall {

        enumerateChildNodesWithName("wallPair", usingBlock: ({
            (node, error) in

            node.speed = 0
            self.removeAllActions()

        }))
        if died == false{
            died = true
            Ball.physicsBody?.velocity = CGVectorMake(0, 0)

            createBTN()
        }
    }
}

I need a second collision detection that is completely separate from the above code^^. How do I make them separate? You can't have two didBeginContact's I don't think. I hope this isn't too vague or unclear. So obviously I need a second node, calling it colorNode. How would I detect a collision between my ball and colorNode (colorNode is about 200 pixels below my scoreNode, so they aren't in the same position), without messing up my code that detects collision between the ball and the wall?

You do not need a separate collision detection. What you need to do is to handle things in didBeginContact . All those if-else checks with their || and && becomes quite unwieldy. (Exemplified by the fact that your last else performs a check that's already been performed in the former else ).

The below code is an OK-ish attempt to make the if-logic more sensible. Creating a Bool to handle the presence for each of the types we're interested in.

func didBeginContact(contact: SKPhysicsContact) {
    let firstBody = contact.bodyA
    let secondBody = contact.bodyB

    let ballWasContacted = firstBody.categoryBitMask == PhysicsCat.Ball || secondBody.categoryBitMask == PhysicsCat.Ball
    let wallWasContacted = firstBody.categoryBitMask == PhysicsCat.Wall || secondBody.categoryBitMask == PhysicsCat.Wall
    let scoreWasContacted = firstBody.categoryBitMask == PhysicsCat.Score || secondBody.categoryBitMask == PhysicsCat.Score

Now that this logic has been defined in a fairly reasonable manner you come to the actual collision-checking where you really reap the rewards:

if ballWasContacted {
    if scoreWasContacted {
        score += 1
        scoreLbl.text = "\(score)"
        let scoreNode = firstBody.categoryBitMask == PhysicsCat.Score ? firstBody.node : secondBody.node
        scoreNode!.removeFromParent()
    } else if wallWasContacted {
        enumerateChildNodesWithName("wallPair", usingBlock: ({
            (node, error) in
            node.speed = 0
            self.removeAllActions()
        }))
        if died == false {
            died = true
            createBTN()
            fallDie()
        }
    }
}

This should make it a lot easier to handle another ball vs. something collision. You just need a PhysicsCat.Color and another Bool . Then just hook another else if onto the last.

 else if colorWasContacted {
            // Do stuff
        }

Note: It's a good idea to also follow conventions. I'm thinking about your naming, do not abbreviate words. scoreLabel not scoreLbl PhysicsCategory not PhysicsCat *

*PhysicsCat? Is that Mr. Schroedinger's late pet?

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