cocos2dx物理引擎和碰撞檢測(三)
阿新 • • 發佈:2019-02-01
上文中講到了如何遍歷物理世界,但是大家想想,我們訪問了世界容器中的每一個物體,只是為了找到一個匹配的物件,這是一個非常耗時的操作,如果遊戲當中存在一百個物件,此時開發者只想找到一個發生碰撞的物件,難道就必須要將一百個物件都訪問一遍嗎?所以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,光線會繼續進行。