SpriteKit类别位掩码无法正常工作

时间:2016-05-07 13:39:27

标签: ios swift sprite-kit bitmask

在我的xcode项目中,我正在尝试创建一个在SKShapeNode点击我创建的世界边界(屏幕边缘)时调用的函数。由于重力,SKShapeNode击中屏幕边缘并向右滚动,但是当接触完成时,函数didBeginContact不会被调用。这是我的代码

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {

struct PhysicsCategory {

    static let redBall: UInt32 =  0x1 << 1
    static let blueBall:  UInt32 = 0x1 << 2
    static let worldBorder: UInt32 = 0x1 << 3

}

let slimeBall = SKSpriteNode(imageNamed: "slimeBall")
let lilyPete = SKSpriteNode(imageNamed:"golden")



override func didMoveToView(view: SKView) {

    self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
    self.physicsWorld.gravity = CGVectorMake(1, 5)
    self.physicsBody?.categoryBitMask = PhysicsCategory.worldBorder
    self.physicsBody!.node?.name = "world"


    self.backgroundColor = UIColor.darkGrayColor()

    let playerCircle = SKShapeNode(circleOfRadius: 15)
    playerCircle.name = "blueCircle"
    playerCircle.fillColor = UIColor.blueColor()
    playerCircle.strokeColor = UIColor.blackColor()
    playerCircle.position = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2)
    playerCircle.physicsBody?.categoryBitMask = PhysicsCategory.redBall
    playerCircle.physicsBody?.contactTestBitMask = PhysicsCategory.worldBorder | PhysicsCategory.redBall
    playerCircle.physicsBody?.collisionBitMask = PhysicsCategory.blueBall | PhysicsCategory.worldBorder

    addChild(playerCircle)

    let enemyCircle = SKShapeNode(circleOfRadius: 50)
    enemyCircle.name = "redCircle"
    enemyCircle.fillColor = UIColor.redColor()
    enemyCircle.strokeColor = UIColor.blackColor()
    enemyCircle.physicsBody = SKPhysicsBody(circleOfRadius: 50)
    enemyCircle.position = CGPointMake(self.frame.size.width / 3, self.frame.size.height / 2)
    enemyCircle.physicsBody?.affectedByGravity = true
    enemyCircle.physicsBody?.dynamic = true
    enemyCircle.physicsBody!.mass = 0.05
    enemyCircle.physicsBody?.categoryBitMask = PhysicsCategory.blueBall
    enemyCircle.physicsBody?.contactTestBitMask = PhysicsCategory.worldBorder | PhysicsCategory.blueBall
    enemyCircle.physicsBody?.collisionBitMask = PhysicsCategory.worldBorder | PhysicsCategory.blueBall

    addChild(enemyCircle)
    enemyCircle.physicsBody?.applyForce(CGVectorMake(-2, -3))



  }


func didBeginContact(contact: SKPhysicsContact) {

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

    if(contact.bodyA.node?.name == "redCircle") && (contact.bodyB.node?.name == "world") || (contact.bodyA.node?.name == "world") && (contact.bodyB.node?.name == "redCircle"){

        print("Contact Made")


    }






}


override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {


    let touch = touches.first! as UITouch
    let touchLocation = touch.locationInNode(self)




}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {


    let touch = touches.first! as UITouch
    let touchLocation = touch.locationInNode(self)

}


}

2 个答案:

答案 0 :(得分:0)

您的红色圆圈的类别位掩码为blueBall,其联系位掩码仅与worldBorder和其他blueBall进行交互。您的蓝色圆圈的类别位掩码为redBall,并且只会与worldBorder和其他blueBall联系。

将您的红色圆圈类别设为实际为redBall,并将您的蓝色圆圈类别设为实际为blueBall,然后您的所有碰撞都应为工作。您可能希望再次运行您的位掩码,因为这两个被交换以确保一切都与其他所有内容发生冲突,因为您没有提及应该如何设置它。

但是,在didBeginContact方法中,您没有正确地包装if语句检查(IMO)。事实上,你完全没有。我建议将支票包裹起来:

if ((contact.bodyA.node?.name == "redCircle") && (contact.bodyB.node?.name == "world")) || ((contact.bodyA.node?.name == "world") && (contact.bodyB.node?.name == "redCircle")) {

这将检查||一侧的所有内容到另一侧的所有内容,然后这将允许您的&&自己驻留,只检查其括号对中的所有内容。

答案 1 :(得分:0)

在DidMoveToView中你需要调用

physicsWorld.contactDelegate = self

否则Contact方法永远不会触发。

此外,对于你的玩家圈子,你没有给它像

这样的物理体
 playerCircle.physicsBody = SKPhysicsBody(...)

将DidBeginContact方法改为此方法,这样您就不必为每次碰撞做2次检查。还可以使用PhysicsCategory来识别它们而不是名称。

func didBeginContact(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 == PhysicsCategory.redBall) && (secondBody.categoryBitMask == PhysicsCategory.worldBorder) {

        // red ball hit world border, do something
    }

    if (firstBody.categoryBitMask == PhysicsCategory.blueBall) && (secondBody.categoryBitMask == PhysicsCategory.worldBorder) {

        // blue ball hit world border, do something
    }
}

另外作为一个提示,在一些物理实体上,你用力展开!

self.physicsBody!.node?.name = "world"
enemyCircle.physicsBody!.mass = 0.05.
如果没有找到physicsBody,

会导致崩溃。

总是使用它更好吗?只要你可以,你已经为大多数人做过了。

在给他们一个物理实体之前,也尝试给你的精灵他们的位置,否则你会得到一些意想不到的结果。

 enemyCircle.position = CGPointMake(self.frame.size.width / 3, self.frame.size.height / 2)
 enemyCircle.physicsBody = SKPhysicsBody(circleOfRadius: 50)
 enemyCircle.physicsBody.categoryBitMask = ...
 ...

希望这有帮助