天天看點

Box2D的Edge Shape的碰撞處理

        有時候兩個body碰撞時需要精确到某條邊,是以在建立body的時候需要建立multiFixture,也就是多個fixture的組合。早期Box2D版本中Polygon Shape有setAsEdge方法設定每條邊的fixture,v2.2.1之後隻有setAsBox方法了。

        方法一:可以在每條邊的位置上加上一個Edge Shape,然後再body中加入這個邊的fixture并儲存起來,碰撞的時候就能判斷是碰到哪條邊了。

        方法二:直接用body的createFixture(edgeShape,density)方法,直接建立一條edge的fixture,因為一般邊不需要其他屬性。預設邊有摩擦力和彈力。

        邊也是以body中點為原點,是以邊的起點和終點要用寬和高的一半來算。

        這樣添加後的碰撞種類(以player站在platform)上為例,可分為:

        1. player的polygonShape和platform的topEdgeShape碰撞。

        2. player的bottomEdgeShape和platform的polygonShape碰撞。

        3. player的polygonShape和platform的polygonShape碰撞。

        4. player的bottomEdgeShape和platform的topEdgeShape不會發生碰撞,因為他們都是Edge類型。

        edgeShape的長度比polygonShape相應邊的長度短一點,這樣分别在判斷左右兩邊和上下兩邊是否發生碰撞時,不會互相影響到。當rightEdge碰撞時,bottomEdge不會發生碰撞;當bottomEdge碰撞時,rightEdge也不會發生碰撞。

        如果edgeShape的長度和polygonShape相應邊的長度一樣的話,當rightEdge碰撞時,bottomEdge的右端也會頂到牆上,發生碰撞,進而産生邏輯錯誤。比如:設定bottomShape發生碰撞時player的狀态是isJump=NO,bottomEdge沒有碰撞時isJump=YES。當player跳起并碰到牆壁時,isJump應該是YES狀态,但bottomEdge檢查到了碰撞,将isJump設為NO,這樣player的其他行為和動作會發生錯誤。

        或者把矩形polygonShape的直角頂點“切掉”,變成八邊形。

如下圖所示:

Box2D的Edge Shape的碰撞處理

1.

//DELTA_LENGTH = 0.5   
    //fixture1 with polygon shape
    b2PolygonShape rectShape;
    rectShape.SetAsBox(size.x/2/PTM_RATIO, size.y/2/PTM_RATIO);
    
    b2FixtureDef fixtureDef1;
    p_body->CreateFixture(&fixtureDef1);
    
    //fixture2 with edge shape
    b2EdgeShape edgeShape;
    edgeShape.Set(b2Vec2((-size.x/2 + DELTA_LENGTH)/PTM_RATIO, (-size.y/2)/PTM_RATIO), 
                  b2Vec2((size.x/2 - DELTA_LENGTH)/PTM_RATIO, (s-size.y/2)/PTM_RATIO));
                        
    b2FixtureDef fixtureDef2;
    fixtureDef2.shape = &edgeShape;
    p_bottomFixture = p_body->CreateFixture(&fixtureDef2);
           

2. 

b2EdgeShape edgeShape;
    edgeShape.Set(b2Vec2((-size.x/2 + DELTA_LENGTH)/PTM_RATIO, (-size.y/2)/PTM_RATIO), 
                  b2Vec2((size.x/2 - DELTA_LENGTH)/PTM_RATIO, (-size.y/2)/PTM_RATIO));

    p_bottomFixture = p_body->CreateFixture(&edgeShape, 0);
           

3 polygonShape必須是凸多邊形,頂點按照逆時針方向依次給出

b2PolygonShape polygonShape;
    b2Vec2 vec[] = {b2Vec2(-size.x/2/PTM_RATIO, -size.y/2/PTM_RATIO), 
                    b2Vec2(size.x/2/PTM_RATIO, -size.y/2/PTM_RATIO), 
                    b2Vec2(size.x/2/PTM_RATIO, -size.y/4/PTM_RATIO), 
                    b2Vec2(size.x/4/PTM_RATIO, size.y/2/PTM_RATIO), 
                    b2Vec2(-size.x/4/PTM_RATIO, size.y/2/PTM_RATIO), 
                    b2Vec2(-size.x/2/PTM_RATIO, -size.y/4/PTM_RATIO)};
    polygonShape.Set(vec, 6);
    b2FixtureDef fixtureDef1;
    fixtureDef1.shape = &polygonShape;
    fixtureDef1.density = dens;
    fixtureDef1.friction = f;
    fixtureDef1.restitution = rest;
    p_polygonFixture = p_body->CreateFixture(&fixtureDef1);
           

繼續閱讀