2010-03-26 48 views
2

我在C#/ XNA中使用Box2dx。我想寫確定是否機構可以在一個給定的點不存在與任何碰撞的功能:Box2dx:World.QueryAABB的用法?

/// <summary> 
    /// Can gameObject exist with start Point without colliding with anything? 
    /// </summary> 
    internal bool IsAvailableArea(GameObjectModel model, Vector2 point) 
    { 
     Vector2 originalPosition = model.Body.Position; 
     model.Body.Position = point; // less risky would be to use a deep clone 

     AABB collisionBox; 
     model.Body.GetFixtureList().GetAABB(out collisionBox); 

     // how is this supposed to work? 
     physicsWorld.QueryAABB(x => true, ref collisionBox); 

     model.Body.Position = originalPosition; 
     return true; 
    } 

有沒有一種更好的方式去這樣做呢? World.QueryAABB應該如何工作?

這是一個較早的嘗試。它被打破;它總是返回false。

/// <summary> 
    /// Can gameObject exist with start Point without colliding with anything? 
    /// </summary> 
    internal bool IsAvailableArea(GameObjectModel model, Vector2 point) 
    { 
     Vector2 originalPosition = model.Body.Position; 
     model.Body.Position = point; // less risky would be to use a deep clone 

     AABB collisionBox; 
     model.Body.GetFixtureList().GetAABB(out collisionBox); 

     ICollection<GameObjectController> gameObjects = worldQueryEngine.GameObjectsForPredicate(x => ! x.Model.Passable); 

     foreach (GameObjectController controller in gameObjects) 
     { 
      AABB potentialCollidingBox; 
      controller.Model.Body.GetFixtureList().GetAABB(out potentialCollidingBox); 

      if (AABB.TestOverlap(ref collisionBox, ref potentialCollidingBox)) 
      { 
       model.Body.Position = originalPosition; 
       return false; // there is something that will collide at this point 
      } 
     } 
     model.Body.Position = originalPosition; 
     return true; 
    } 

回答

4

World.QueryAABB聲明如下:

public void QueryAABB(Func<Fixture, bool> callback, ref AABB aabb) 

作爲其第二個參數傳遞軸對準包圍盒你有興趣,自然。

作爲第一個參數,您需要傳入Func<Fixture, bool>類型的代理。如果您對代表不熟悉,可以暫時將其隱藏起來:認爲這是您需要傳遞的線索:a)代碼中的現有函數或b)一個新函數,您可以動態聲明if你喜歡。

當您調用QueryAABB時,每次找到與您提供的邊界框重疊的對象時,它都會回撥您。如果發現三個對象與您的邊界框重疊,它會調用您的函數三次,每個對象一次。您每次可以返回true說「謝謝,繼續搜索」或false說「這很好,不要再搜索」。

所以一個例子用法是:

private bool m_foundCount = 0; 

internal bool IsAvailableArea(GameObjectModel model, Vector2 point) 
{ 
    ... 
    m_foundCount = 0; 
    physicsWorld.QueryAABB(OnFoundSomething, ref collisionBox); 
    Debug.WriteLine(string.Format("Found {0} fixtures in total", m_foundCount)); 
    .. 
} 

internal bool OnFoundSomething(Fixture found) 
{ 
    Debug.WriteLine(string.Format("Found fixture {0}", found)); 
    ++m_foundCount; 
    return true; // true to carry on searching, false when done 
} 

(順便說一句,這裏曾經是更長的時間,需要你早期版本的C#明確環繞OnFoundSomething代表,一拉:

physicsWorld.QueryAABB(new Func<Fixture, bool>(OnFoundSomething), ref collisionBox); 

值得慶幸的是這一點,相關的語法不再通常需要。)

的另一種方式做到這一點是一個lambda函數,這是數學家說幾句話您在飛行中定義的無名函數。

等效lambda函數上述OnFoundSomething功能是:

found => 
{ 
    Debug.WriteLine(string.Format("Found fixture {0}", found)); 
    ++m_foundCount; 
    return true; 
} 

所以,唯一的區別是,該功能不會有一個名字,它的返回值和參數的類型從摸索出您在其中使用它的上下文。如:

internal bool IsAvailableArea(GameObjectModel model, Vector2 point) 
{ 
    ... 
    m_foundCount = 0; 
    physicsWorld.QueryAABB(found => 
    { 
     Debug.WriteLine(string.Format("Found fixture {0}", found)); 
     ++m_foundCount; 
     return true; 
    }, ref collisionBox); 
    Debug.WriteLine(string.Format("Found {0} fixtures in total", m_foundCount)); 
    .. 
} 

關於你剛纔的嘗試,我不能肯定,但我懷疑它可能已經返回false都是因爲你遍歷所有的遊戲對象,包括你在測試一個時間;因此它會與自己「碰撞」。