碰撞位掩码是如何工作的?斯威夫特/雪碧套件

     2023-02-15     89

关键词:

【中文标题】碰撞位掩码是如何工作的?斯威夫特/雪碧套件【英文标题】:How does collisionBitMask work? Swift/SpriteKit 【发布时间】:2015-09-15 13:27:49 【问题描述】:

据我所知,Physics 物体的默认设置是在它们相互碰撞时相互反弹,直到您将它们的 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 个球和我的边框。我可以得到我想要的碰撞检测,但是当我添加边框体的类别位掩码时,它允许球穿过和离开屏幕,这是我不想要的。

我还希望球相互反弹,但只有当我注释掉其中一个球的 categoryBitMask 时,它们才会反弹。否则它们会互相穿过。

这对我来说完全没有意义,因为这些项目中的每一个都有不同的碰撞位掩码。有时我也有这样的情况,将所有数字设置为 5 将允许所有内容相互通过,但将其全部设置为 6 将允许所有内容相互碰撞。

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

【问题讨论】:

【参考方案1】:

您无法获得所需的行为,因为您没有正确设置类别、接触和碰撞位掩码。这是一个关于如何设置它的示例:

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 - 一个掩码,定义哪些类别的物体会导致与当前物理物体的交叉通知。

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

collisionBitmask - 定义哪些类别的物理体可以与此物理体发生碰撞的掩码。

当两个物理体相互接触时,可能会发生碰撞。 将此主体的碰撞掩码与其他主体的类别进行比较 通过执行逻辑与运算来屏蔽。如果结果是非零 值,这个物体会受到碰撞的影响。每个身体独立 选择是否要被对方影响。为了 例如,您可以使用它来避免碰撞计算 对身体的速度进行微不足道的变化。

所以基本上,要设置所有这些,您应该问自己以下问题:

好的,我有一个绿色球,一个红色球,以及场景中的墙壁对象。我希望在哪些物体之间发生碰撞,或者何时注册联系人?我想要一个绿色和一个红色的球相互碰撞并撞到墙上。不是问题。我将首先正确设置类别,然后我将设置这样的碰撞位掩码:

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

希望这会有所帮助。

【讨论】:

惊人的答案,非常感谢您花时间写下所有这些。它运行良好。 “问问自己这个”部分肯定澄清了我的困惑。非常感谢,非常感谢! 如果你有超过 32 个呢? @Abcdefg 如何在 didEnd 函数中检测到碰撞结束? 非常棒的答案——非常感谢!现在在这个话题上挣扎了几天。你的“问你自己”部分是我所见过的最好的解释。【参考方案2】:

只是想在这里添加一些东西,如果接触或碰撞无法正常工作,您需要确保在应用 bitMask 之前先分配physicsBody 形状。

位掩码无效示例:

        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];

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

【讨论】:

如何记录位掩码

】如何记录位掩码【英文标题】:Howtologabitmask【发布时间】:2012-01-2612:30:01【问题描述】:我正在调用[[UIApplicationsharedApplication]enabledRemoteNotifications],它返回一个位掩码。我如何NSLog位掩码来了解位掩码是如何组成的以及哪些通... 查看详情

PHP中基于位掩码获取数组值

】PHP中基于位掩码获取数组值【英文标题】:GetarrayvaluesbasedonbitmaskinPHP【发布时间】:2014-12-1722:00:28【问题描述】:我有一个用于位掩码的32位整数和一个包含32个值的数组。如何从数组中仅获取那些索引对应于位掩码中非零位... 查看详情

SpriteKit 碰撞检测不起作用

】SpriteKit碰撞检测不起作用【英文标题】:SpriteKitcollisionDetectiondoesnotwork【发布时间】:2014-05-1320:47:56【问题描述】:我以为我了解位掩码、CategoryBitMasks和CollisionBitMasks的概念,但事实证明我不了解;-(但我不明白为什么。我为碰... 查看详情

什么是位掩码?

】什么是位掩码?【英文标题】:WhatisBitMasking?【发布时间】:2012-05-1615:06:44【问题描述】:我对C编程相当陌生,但我遇到了位掩码。有人可以向我解释位掩码的一般概念和功能吗?非常感谢示例。【问题讨论】:我知道不应该... 查看详情

使用固定的 SKPhysicsJoint 将作为孩子的平台检测命中框附加到玩家精灵会更改玩家的碰撞和检测位掩码

...作为孩子的平台检测命中框附加到玩家精灵会更改玩家的碰撞和检测位掩码【英文标题】:UsingafixedSKPhysicsJointtoattachaplatformdetectionhitboxasachildtoaplayerspritechangesplayer\'scollisionanddetectionbitmasks【发布时间】:2017-12-2223:43:25【问题描述... 查看详情

位掩码:如何确定是不是只设置了一位

】位掩码:如何确定是不是只设置了一位【英文标题】:Bitmask:howtodetermineifonlyonebitisset位掩码:如何确定是否只设置了一位【发布时间】:2013-04-1114:44:09【问题描述】:如果我有一个基本的位掩码...cat=0x1;dog=0x2;chicken=0x4;cow=0x8;//O... 查看详情

使用 SIMD,如何将 8 位掩码扩展为 16 位掩码?

】使用SIMD,如何将8位掩码扩展为16位掩码?【英文标题】:UsingSIMD,howcanIexpanda8-bitmaskto16-bitmask?【发布时间】:2017-02-2103:26:32【问题描述】:我正在尝试使用simd重写这段代码:int16_tv;int32_ta[16];int8_tb[32];...((int16_t*)a[i])[0]=b[i]==1?-v:v... 查看详情

斯威夫特:分数增加两次,因为碰撞被检测到两次?

】斯威夫特:分数增加两次,因为碰撞被检测到两次?【英文标题】:Swift:scoreincreasestwicebecausecollisionisdetectedtwice?【发布时间】:2015-06-1505:48:11【问题描述】:我正在快速构建一个精灵套件游戏,当检测到2个节点之间的碰撞时... 查看详情

如何更改此数组以将物理体赋予每个单独的节点(位掩码)?

】如何更改此数组以将物理体赋予每个单独的节点(位掩码)?【英文标题】:Howtochangethisarraytogivephysicsbodiestoeachindividualnode(bitmasks)?【发布时间】:2016-01-1901:54:27【问题描述】:我的屏幕顶部有骰子掉下来。有五种不同的面孔... 查看详情

如何在 Swift 中为 SpriteKit 定义类别位掩码枚举?

】如何在Swift中为SpriteKit定义类别位掩码枚举?【英文标题】:HowtodefinecategorybitmaskenumerationforSpriteKitinSwift?【发布时间】:2014-07-2700:11:33【问题描述】:为了在Objective-C中定义一个类别位掩码枚举,我曾经键入:typedefNS_OPTIONS(NSUIn... 查看详情

位掩码是不是可以与位中的“访问数组”相媲美?

】位掩码是不是可以与位中的“访问数组”相媲美?【英文标题】:Isbitmaskingcomparableto"accessinganarray"inbits?位掩码是否可以与位中的“访问数组”相媲美?【发布时间】:2019-01-1523:41:06【问题描述】:对于我见过的所有位... 查看详情

如何使用位掩码在 Swift 2.2 中自定义 UIControlState?

】如何使用位掩码在Swift2.2中自定义UIControlState?【英文标题】:HowtohavecustomUIControlStateinSwift2.2usingbitmasks?【发布时间】:2016-08-2321:33:57【问题描述】:我有一个自定义UIButton,它具有一些我希望它具有的独特状态:enumPositionControl... 查看详情

C中的位掩码

】C中的位掩码【英文标题】:BitmaskinC【发布时间】:2010-09-2321:48:17【问题描述】:用m设置位前面是k未设置位,然后是n未设置位,在C中构造位掩码的最佳方法是什么:00..011..100..0kmn例如,k=1、m=4、n=3会产生位掩码:01111000【问... 查看详情

SKPhysicsJoint:接触和碰撞不起作用

】SKPhysicsJoint:接触和碰撞不起作用【英文标题】:SKPhysicsJoint:Contactsandcollisionsnotworking【发布时间】:2014-03-2401:08:19【问题描述】:在IOS7.1上,使用SpriteKit,我创建了两个简单的矩形精灵和对应的物理实体。我设置了接触和碰撞... 查看详情

这个按位汉明(31,26)编码器如何在 C 中工作? (位掩码)

】这个按位汉明(31,26)编码器如何在C中工作?(位掩码)【英文标题】:Howdoesthisbitwisehamming(31,26)encoderworkinC?(Bitmasking)【发布时间】:2022-01-0609:48:01【问题描述】:我了解各个操作是什么(例如按位AND和OR),但我不明白为什... 查看详情

使用单色 QImage

...2012-11-2502:25:13【问题描述】:我正在尝试从QPixmap中提取位掩码并将其传递给OpenCV。我的位掩码是通过“绘画”操作创建的。到目前为止,我的过程是:创建一个QPixmap,QPixmap::fill(QColor(0,0,0,0))并使用QPainter和QPainter::setPen(QColor(255 查看详情

Django - 模板位掩码检查

】Django-模板位掩码检查【英文标题】:Django-Templatebitmaskcheck【发布时间】:2014-02-1019:53:31【问题描述】:考虑这个列表:options=[\'name\':\'Option1\',\'plan\':0b001,,\'name\':\'Option2\',\'plan\':0b010,,\'name\':\'Option3\',\'plan\':0b110,,]问题:如何将... 查看详情

奇怪的知识——位掩码(代码片段)

在春节假期无聊刷手机的时候,偶然间看到了一篇关于“位掩码”的文章,本身就是奇怪知识的它可以用来解决一些奇怪的问题,实在是非常有趣。位运算符在了解“位掩码”之前,首先要学会位运算符。我们知道,在计算机中... 查看详情