2 Stimmen

Box2dx: Verwendung von World.QueryAABB?

Ich verwende Box2dx mit C#/XNA. Ich versuche, eine Funktion zu schreiben, die feststellt, ob ein Körper an einem bestimmten Punkt existieren kann, ohne mit etwas zu kollidieren:

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

Gibt es einen besseren Weg, dies zu tun? Wie ist World.QueryAABB funktionieren soll?

Hier ist ein früherer Versuch. Er ist fehlerhaft; er gibt immer false zurück.

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

4voto

El Zorko Punkte 3179

World.QueryAABB wird wie folgt deklariert:

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

Als zweiten Parameter übergeben Sie natürlich die achsenausgerichtete Bounding Box, an der Sie interessiert sind.

Als ersten Parameter müssen Sie einen Delegaten vom Typ Func<Fixture, bool> . Wenn Sie mit Delegaten nicht vertraut sind, können Sie sie vorerst übergehen: Betrachten Sie dies als Hinweis darauf, dass Sie entweder a) eine bestehende Funktion in Ihrem Code oder b) eine neue Funktion übergeben müssen, die Sie bei Bedarf spontan deklarieren können.

Wenn Sie QueryAABB aufrufen, ruft es Sie jedes Mal zurück, wenn es ein Objekt findet, das den von Ihnen angegebenen Begrenzungsrahmen überlappt. Wenn drei Objekte gefunden werden, die Ihren Begrenzungsrahmen überlappen, wird Ihre Funktion dreimal aufgerufen, einmal pro Objekt. Jedes Mal können Sie zurückgeben true zu sagen: "Danke, weitersuchen" oder false zu sagen: "Das ist gut, suchen Sie nicht weiter".

Ein Anwendungsbeispiel wäre also:

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
}

(Nebenbei bemerkt, war dies früher sogar noch länger; frühere Versionen von C# erforderten, dass Sie explizit einen Delegaten um OnFoundSomething wickeln, a la:

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

Zum Glück ist diese und ähnliche Syntax nicht mehr allgemein erforderlich).

Die andere Möglichkeit ist eine Lambda-Funktion, was in der Mathematik für eine namenlose Funktion steht, die Sie spontan definieren.

Die äquivalente Lambda-Funktion zur obigen OnFoundSomething-Funktion ist:

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

Der einzige Unterschied besteht also darin, dass die Funktion keinen Namen hat und der Typ ihres Rückgabewerts und ihres Arguments aus dem Kontext, in dem sie verwendet wird, ermittelt wird. Wie in:

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));
    ..
}

In Bezug auf Ihre früheren Versuch, ich bin mir nicht sicher, aber ich vermute, es kann zurückgeben false die ganze Zeit, weil Sie über alle Spiel-Objekte, einschließlich der, die Sie getestet wurden iteriert wurden; daher wäre es "kollidieren" mit sich selbst.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X