【问题标题】:How are bodyA and bodyB determined in SKPhysicsContact?物理接触中的身体和身体是如何确定的?
【发布时间】:2017-01-08 19:32:41
【问题描述】:

我在 SKScene 中有两个不同的固定 SKPhysicsBody。两者之间的唯一区别是它们的 categoryBitMask。一个的 categoryBitMask 为 512,另一个为 1024。

static const u_int32_t kWallCategory = 0x1 << 9;         //512  
static const u_int32_t kStructureCategory = 0x1 << 10;    //1024

在我的程序中,我有一个标准的联系人处理程序,从 -(void)didBeginContact:(SKPhysicsContact *)contact 开始调用:

-(void)handleContact:(SKPhysicsContact*)contact {
     SKPhysicsBody *bodyA = contact.bodyA;
     SKPhysicsBody *bodyB = contact.bodyB;
     int type1 = contact.bodyA.categoryBitMask;
     int type2 = contact.bodyB.categoryBitMask;

在我的程序中,我需要确定一个动态物体和两个固定物体之一之间的接触向量。为此,我访问了 SKPhysicsContact 的 contactNormal 属性

CGVector c = contact.contactNormal;

不过,我注意到接触矢量不一致,我确定这是因为有时 SKPhysicsContact 的 bodyA 是固定体,有时 bodyA 是动态体。

例如,当子弹(动态体)从左侧击中建筑物(固定体)时,我希望每次的接触向量都是(-1,0)。目前,接触向量有时是(-1,0)(左起),有时是(1,0)(右起),这都取决于contact.bodyA是哪个主体。

我的问题:假设所有其他条件都相同(物理属性等),什么决定了 SKPhysicsContact 中的 bodyA 和 bodyB 是什么?

【问题讨论】:

    标签: objective-c skphysicsbody skphysicscontact


    【解决方案1】:

    在修改了每个 SKPhysicsBody 的几个方面(质量、摩擦、categoryBitmask 等)后,我确定 SKPhysicsContact.bodyASKPhysicsContact.bodyB 之间的决定是基于单独关于何时将 SKPhysicsBody 添加到场景中

    突出差异的示例:

    SKPhysicsBody *bullet 从左侧点击SKPhysicsBody *building

    案例1:如果*building被添加到场景之前*bulletSKPhysicsContact.contactNormal是:(-1,0)因为SKPhysicsContact.bodyA*building,所以接触向量是*building 的联系地址(即左侧)

    案例2:如果*building被添加到场景之后 *bulletSKPhysicsContact.contactNormal是:(1,0)因为SKPhysicsContact.bodyA现在是*bullet,因此接触向量是 *bullet 的联系地址(即右侧)

    问题

    因为*bullet*building 实体在我的程序中的不同时间添加,所以我需要实现一个我一直知道SKPhysicsContact.bodyASKPhysicsContact.bodyB 是什么的方法,更重要的是,一种保持SKPhysicsContact.contactNormal 一致。

    解决方案

    确定您需要确定碰撞来自何处的SKPhysicsBody,并设置physicsBody.categoryBitMask

    static const u_int32_t kProjectileCategory = 0x1 << 1;  //Dynamic body 
    //Make everything with bitmask > 32 will be set for the fixed bodies
    static const u_int32_t kStructureCategory = 0x1 << 10;  //Fixed body
    

    然后,在联系人处理程序中:

    -(void)handleContact:(SKPhysicsContact*)contact {
    //bodyA will be the SKPhysicsBody that was added to the SKScene before bodyB
    SKPhysicsBody *bodyA = contact.bodyA;
    
    //bodyB will be the SKPhysicsBody that was added to the SKScene after bodyA
    SKPhysicsBody *bodyB = contact.bodyB;
    
    int categoryBitmask1 = contact.bodyA.categoryBitMask;
    int categoryBitmask2 = contact.bodyB.categoryBitMask;
    
    CGVector v;
    
    //If the categoryBitmask of bodyA is lower, we will get the contact vector from the Dynamic body, which we don't want
    if (categoryBitmask1 < categoryBitmask2)
    {
        //Since we always want the contact vector determined FROM the fixed body (higher category bitmask), we have to get the reciprocal contact vector in the case that bodyA is the dynamic (non-fixed) body
        v = CGVectorMake(contact.contactNormal.dx * -1, contact.contactNormal.dy * -1);
    } else {
        //If the categoryBitmask
        v = contact.contactNormal;
    }
    

    【讨论】:

    • 这是很棒的侦探。您的结论是,应该始终测试哪个主体是哪个(假设它对您的联系处理程序所做的事情很重要)是正确的,但是在此过程中存在一个问题:始终测试的原因不是很难控制哪些订单主体进入场景。Apple 不保证身体 A 和 B 将处于任何确定性顺序 - 您已将其与创建顺序相关联,但不能保证所有物体都相同设备和操作系统版本。
    猜你喜欢
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 2017-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-26
    • 2013-11-15
    相关资源
    最近更新 更多