SKPhysicsContact is there any way to determine which body is A and B?

时光毁灭记忆、已成空白 提交于 2021-02-19 03:06:36

问题


in SpriteKit we detect the in the didBeginContact method. but this looks a bit stupid to do something like that: func didBeginContact(contact: SKPhysicsContact) {

    if let contactA = contact.bodyA.node?.name {

        if let contactB = contact.bodyB.node?.name {

            //now that we have safely unwrapped these nodes, we can operate on them

            if contactA == "ball" {

                collisionBetweenBall(contact.bodyA.node!, object: contact.bodyB.node!)

            } else if contactB == "ball" {

                collisionBetweenBall(contact.bodyB.node!, object: contact.bodyA.node!)

            }

        }

    }

}

is there any way I can ensure that bodyA is always a ball? is there any rules related to categorybitmask?


回答1:


If you are using simple categories, with each physics body belonging to only one category, then this alternative form of didBeginContact may be more readable:

func didBeginContact(contact: SKPhysicsContact) {
    let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

switch contactMask {

   case categoryBitMask.ball | categoryBitMask.something:
       print("Collision between ball and something")
       let ballNode = contact.bodyA.categoryBitMask == categoryBitMask.ball ? contact.bodyA.node! : contact.bodyB.node!
       ballNode.pop()
       score += 10

   default :
       //Some other contact has occurred
       print("Some other contact")
   }
}

Note that if your categories are more complicated, this won't work as the simple AND tests (categoryBitMask.ball | categoryBitMask.something) won't match.




回答2:


Usually you would do this

First you would store your bit mask categories if you are not doing it already.

enum PhysicsCategory {
     static let ball: UInt32 =  0x1 << 0
     static let wall: UInt32 =  0x1 << 1
     static let enemy: UInt32 = 0x1 << 2
}

and than assign them like so to your sprites

 ball.physicsBody?.categoryBitMask = PhysicsCategory.ball
 ball.physicsBody?.contactTestBitMask = PhysicsCategory.wall | PhysicsCategory.enemy

 wall.physicsBody?.categoryBitMask = PhysicsCategory.wall
 wall.physicsBody?.contactTestBitMask = 0 

 enemy.physicsBody?.categoryBitMask = PhysicsCategory.enemy
 enemy.physicsBody?.contactTestBitMask = 0 

Note: Because ball checks for contacts with both wall and enemy in this example you would not need to tell wall or enemy to check contacts with ball. Its fine to do it on 1 physics body so you can set it to 0 on the others unless they have other specific contacts to look for.

Than you can check for them in the contact method like so without the double if statements.

func didBegin(_ contact: SKPhysicsContact) {

    let firstBody: SKPhysicsBody
    let secondBody: SKPhysicsBody

    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
        firstBody = contact.bodyA
        secondBody = contact.bodyB
    } else {
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    }


    // Ball hit wall or wall hit ball
    if (firstBody.categoryBitMask == PhysicsCategory.ball) && (secondBody.categoryBitMask == PhysicsCategory.wall) {

          // Some code
    }

    // Ball hit enemy or enemy hit ball
    if (firstBody.categoryBitMask == PhysicsCategory.ball) && (secondBody.categoryBitMask == PhysicsCategory.enemy) {

          // Some code
    }
}

Also do not forget to set the delegate in didMoveToView of your scene for this to work.

physicsWorld.contactDelegate = self

Hope this helps



来源:https://stackoverflow.com/questions/40436300/skphysicscontact-is-there-any-way-to-determine-which-body-is-a-and-b

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!