我在C#/ XNA中使用Box2dx。我正在尝试编写一个函数,该函数确定某个物体是否可以存在于给定点而不会与任何物体发生碰撞:

    /// <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;
    }

最佳答案

World.QueryAABB的声明如下:

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


作为第二个参数,您自然会传递您感兴趣的轴对齐的边界框。

作为第一个参数,您需要传递Func<Fixture, bool>类型的委托。如果您不熟悉委托,则可以暂时忽略它们:考虑一下这条线索,您需要传入a)代码中的现有函数或b)您可以即时声明的新函数。你喜欢。

调用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函数,这是数学家所说的动态定义的无名函数。

与上述OnFoundSomething函数等效的lambda函数为:

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,因为您要遍历所有游戏对象,包括您正在测试的对象。因此它本来会与自己“碰撞”。

关于c# - Box2dx:World.QueryAABB的用法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2525713/

10-11 02:16