collisionBitMask如何工作?夫特/ SpriteKit

时间:2015-06-29 07:04:48

标签: swift sprite-kit skphysicsbody

据我所知,物理体的默认值是相互反弹,直到你将collisionBitMask设置为相等的数字为止。

但是,我遇到了一个很大的问题,因为我相信的碰撞比特看起来应该很简单。

    let RedBallCategory  : UInt32 = 0x1 << 1
    let GreenBallCategory: UInt32 = 0x1 << 2
    let RedBarCategory : UInt32 = 0x1 << 3
    let GreenBarCategory : UInt32 = 0x1 << 4
    let WallCategory : UInt32 = 0x1 << 5


      greenBall.physicsBody?.categoryBitMask = GreenBallCategory
       greenBall.physicsBody?.contactTestBitMask = RedBarCategory
        greenBall.physicsBody?.collisionBitMask = GreenHealthCategory

 redBall.physicsBody?.categoryBitMask = RedBallCategory
        redBall.physicsBody?.contactTestBitMask = GreenBarCategory
       redBall.physicsBody?.collisionBitMask = RedHealthCategory

   let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
    self.physicsBody = borderBody
    self.physicsBody?.friction = 0
    borderBody.contactTestBitMask = RedBallCategory | GreenBallCategory
   borderBody.categoryBitMask = WallCategory

所以在这里我有2个球和我的边界身体。我可以得到我想要的碰撞检测,但是当我添加边框体的类别位掩码时,它允许球通过和离开屏幕,这是我不想要的。

我也希望球能够相互反弹,但只有当我注意到其中一个球的类别时,他们才能反弹。否则他们会互相通过。

这对我来说完全没有意义,因为每个项目都有不同的碰撞比特。我也有时将所有数字设置为5将允许所有数据相互通过,但是将其全部设置为6将允许所有内容相互碰撞。

碰撞位掩码究竟是如何工作的,是否有适当的方法来管理大量交叉碰撞规则?

2 个答案:

答案 0 :(得分:47)

您无法获得所需的行为,因为您尚未正确设置类别,接触和碰撞位掩码。以下是如何设置此功能的示例:

greenBall.physicsBody?.categoryBitMask = GreenBallCategory //Category is GreenBall
greenBall.physicsBody?.contactTestBitMask = RedBarCategory | WallCategory //Contact will be detected when GreenBall make a contact with RedBar or a Wall (assuming that redBar's masks are already properly set)
greenBall.physicsBody?.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory //Collision will occur when GreenBall hits GreenBall, RedBall or hits a Wall

redBall.physicsBody?.categoryBitMask = RedBallCategory //Category is RedBall
redBall.physicsBody?.contactTestBitMask = GreenBarCategory | GreenBallCategory | WallCategory //Contact will be detected when RedBall make a contact with GreenBar , GreenBall or a Wall
redBall.physicsBody?.collisionBitMask = RedBallCategory | GreenBallCategory | WallCategory //Collision will occur when RedBall meets RedBall, GreenBall or hits a Wall

let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody = borderBody
self.physicsBody?.friction = 0
borderBody.contactTestBitMask = RedBallCategory | GreenBallCategory //Contact will be detected when red or green ball hit the wall
borderBody.categoryBitMask = WallCategory
borderBody.collisionBitMask = RedBallCategory | GreenBallCategory // Collisions between RedBall GreenBall and a Wall will be detected

我建议你阅读有关categoryBitMask的文档,这是一个定义物理机构所属类别的掩码:

  

场景中的每个物理主体最多可分配32个不同的物理主体   类别,每个类别对应于位掩码中的一个位。你定义   游戏中使用的蒙版值。与...结合   collisionBitMask和contactTestBitMask属性,你定义哪个   物理机构互相交流,当你的游戏得到通知时   这些互动。

contactTestBitMask - 一个掩码,用于定义哪些类别的物体会导致与当前物理体的交集通知。

  

当两个物体共享相同的空间时,每个物体的类别掩码都是   通过执行逻辑来测试另一个身体的接触面罩   和操作。如果任一比较结果为非零值,则为   创建SKPhysicsContact对象并将其传递给物理世界   代表。为获得最佳性能,仅在触点掩码中设置位   您感兴趣的互动。

collisionBitmask - 一个掩码,用于定义哪些类别的物理实体可以与此物理实体发生碰撞。

  

当两个物理实体相互接触时,可能会发生碰撞。   该身体的碰撞面具与其他身体的类别进行比较   通过执行逻辑AND操作进行掩码。如果结果是非零   值,这个身体受到碰撞的影响。每个身体独立   选择是否想要受到其他身体的影响。对于   例如,您可以使用它来避免碰撞计算   对身体的速度做出微不足道的改变。

所以基本上,要设置所有这些,你应该问自己的东西:

好的,我有一个绿色的球,一个红色的球,还有一些墙上的物体。在哪些机构之间我想要发生碰撞,或者我想要注册联系人?我想要一个绿色和红色的球相互碰撞并碰撞墙壁。不是问题。我将首先正确设置类别,然后我将设置碰撞位掩码,如下所示:

greenBall.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory; //greenBall will collide with greenBall, redBall and a wall
redBall.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory

wall.collisionBitMask = GreenBall | RedBall

现在,我想检测一些联系人何时发生(didBeginContact:方法)...但我不想收到有关所有可能联系人的通知,而是要通知球之间的联系(球和墙之间的接触将被忽略)。因此,设置contactTestBitMasks来实现此目的:

greenBall.contactTestBitMask = GreenBallCategory | RedBallCategory;
redBall.contactTestBitMask = GreenBallCategory | RedBallCategory;

就是这样。重要的是,当您不使用接触检测时,不应设置contactTestBitMask。这是因为性能原因。如果您不需要碰撞检测,并且只对检测联系人感兴趣,则可以设置collisionBitMask = 0

重要的:

确保您已设置物理世界的联系人委托,以便使用didBeginContactdidEndContact方法:

self.physicsWorld.contactDelegate = self; //where self is a current scene

希望这有点帮助。

答案 1 :(得分:1)

只需在此处添加一些内容,如果接触或碰撞无法正常工作,则需要确保在应用bitMask之前先分配PhysicalBody形状。

不起作用的位掩码的示例:

        SKSpriteNode *bird = [SKSpriteNode spriteNodeWithImageNamed:@"bird1.png"];
        bird.name = @"bird";
        bird.physicsBody.categoryBitMask = birdCategory;
        bird.physicsBody.contactTestBitMask = wallCategory | scoreCategory;
        bird.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:bird.size.width/2.7];
        bird.position = CGPointMake(_mySize.width/3.0, 2*_mySize.height/3.0);
        [self addChild:bird];

工作一个:

    SKSpriteNode *bird = [SKSpriteNode spriteNodeWithImageNamed:@"bird1.png"];
    bird.name = @"bird";
    bird.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:bird.size.width/2.7];
    bird.physicsBody.categoryBitMask = birdCategory;
    bird.physicsBody.contactTestBitMask = wallCategory | scoreCategory;
    bird.position = CGPointMake(_mySize.width/3.0, 2*_mySize.height/3.0);
    [self addChild:bird];

无论如何可能只是一个新手错误,但是我在这里分享,因为这是导致我无法正常工作的原因。