1. 程式人生 > >cocos2dx物理引擎和碰撞檢測(三)

cocos2dx物理引擎和碰撞檢測(三)

上文中講到了如何遍歷物理世界,但是大家想想,我們訪問了世界容器中的每一個物體,只是為了找到一個匹配的物件,這是一個非常耗時的操作,如果遊戲當中存在一百個物件,此時開發者只想找到一個發生碰撞的物件,難道就必須要將一百個物件都訪問一遍嗎?所以Box2D引擎提供了一種訪問物件的方式:AABB查詢。在Box2D引擎當中,AABB代表了一個固定尺寸的矩形盒子。它是當開發者需要得出一個區域內的所有物件時的解決方法。看程式碼:

AABB查詢例子:

//查詢的回撥函式
class MyQueryCallback:pubilc b2QueryCallback
{
public:
     bool ReportFixture(b2Fixture*fixture)
     {
        //獲得物體連結串列指標
        b2Body* body =fixture->GetBody();
        //喚醒物體
      body->WakeUp();
        //返回true,繼續查詢
      return true;
      }
};
MyQueryCallback callback;
//建立一個AABB物件
b2AABB aabb;
//設定AABB的上邊界
aabb.lowerBound.Set(-1.0f,-1.0f);
//設定AABB的下邊界
aabb.upperBound.Set(1.0f,1.0f);
//開始查詢
myWorld->Query(&callback,aabb);

經過上面的程式碼,我們能夠看到AABB查詢的使用方法。開發者只需要提供一個物理世界座標的AABB盒子和b2QueryCallback的一個回撥函式的實現。只要物理世界中物件的AABB和需查詢的AABB有重合,那麼物理世界物件就會回撥類b2QueryCallback的函式。
光線投射(Ray Casts)

除了AABB區域之外,Box2D引擎當中還提供了另一種物體的查詢方式。那就是開發者可以使用光線投射 去做視線檢查或者掃射。通過實現一個回撥函式的類,並同時提供一個開始點和結束點,讀者就可以執行光線投射。下面例子會獲取光線投射中最近的物體:
光線投射查詢:

class MyRayCastCallback:public b2RayCastCallback
{
public:
      MyRayCastCallback()
      {
         m_fixture =NULL;
      }
      //返回值
    float32 ReportFixture(b2Fixture,const b2Vec2& point,const b2Vec2& normal,float32 fraction)
       {
          //儲存框架
       m_fixture =fixture;
          //儲存交點
       m_point =point;
           //儲存法向量
       m_normal =normal;
          //儲存光線通過的分數距離
       m_fraction =fraction;
          return fraction;
        }
         b2Fixture* m_fixture;
         b2Vec2 m_point;
         b2Vec2 m_normal;
         float32 m_fraction;
};
//回撥函式
MyRayCastCallback callback;
//光線投射的起始點
b2Vec2 point(-1.0f,0.0f);
//光線投射的結束點
b2Vec2 point2(3.0f,1.0f);
//開始光線投射
myWorld->RayCast(&callback,point1,point2);

上述程式碼中回撥函式類MyRayCastCallback是光線投射運算後執行的函式。只要有框架fixture被光線投射穿過時,物理世界就會呼叫回撥函式類中的函式ReportFixture。另外fraction的數值也有一定的意義,用來控制光線投射是否繼續進行。為0代表結束光線投射,為1代表繼續投射,並且沒有和其他形狀相交。為-1表示過濾當前發現的框架fixture,光線會繼續進行。