Box2dx:World.QueryAABB 的用法?
我将 Box2dx 与 C#/XNA 一起使用。我正在尝试编写一个函数来确定物体是否可以存在于给定点而不与任何物体发生碰撞:
/// <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;
}
I'm using Box2dx with C#/XNA. I'm trying to write a function that determines if a body could exist in a given point without colliding with anything:
/// <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;
}
Is there a better way to go about doing this? How is World.QueryAABB
supposed to work?
Here is an earlier attempt. It is broken; it always returns 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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
World.QueryAABB 的声明如下:
作为其第二个参数,您自然会传递您感兴趣的轴对齐边界框。
作为第一个参数,您需要传入
Func
类型的委托。如果您不熟悉委托,您现在可以忽略它们:将此视为您需要传入 a) 代码中现有函数或 b) 可以动态声明的新函数的线索,如果你喜欢。当您调用 QueryAABB 时,每次它发现与您提供的边界框重叠的对象时,它都会回调您。如果它发现三个对象与您的边界框重叠,它将调用您的函数三次,每个对象一次。每次您都可以返回
true
表示“谢谢,继续搜索”,或返回false
表示“很好,不要再搜索了”。因此,一个示例用法是:(
顺便说一句,这曾经更长;C# 的早期版本要求您显式地将委托包装在 OnFoundSomething 周围,la:
谢天谢地,通常不再需要此语法和相关语法。
)方法是使用 lambda 函数,数学家所说的函数是您动态定义的无名函数。
与上面的 OnFoundSomething 函数等效的 lambda 函数是:
因此,唯一的区别是该函数没有名称,并且其返回值和参数的类型是根据使用它的上下文计算出来的。就像:
关于您之前的尝试,我不确定,但我怀疑它可能一直返回 false,因为您正在迭代所有游戏对象,包括您正在测试的对象;因此它会与自身“碰撞”。
World.QueryAABB is declared like this:
As its second parameter you pass the axis aligned bounding box you're interested in, naturally.
As the first parameter you need to pass in a delegate of type
Func<Fixture, bool>
. If you're not familiar with delegates, you can gloss over them for now: consider this a clue that you need to pass in either a) an existing function in your code or b) a new function which you can declare on the fly if you like.When you call QueryAABB, it will call you back each time it finds an object which overlaps the bounding box you provide. If it finds three objects overlapping your bounding box, it will call your function three times, once per object. Each time you can return
true
to say "thanks, carry on searching" orfalse
to say "that's good, don't search any more".So one example usage would be:
(As an aside, this used to be even longer; earlier versions of C# required you to explicitly wrap a delegate around OnFoundSomething, a la:
Thankfully this and related syntax is no longer generally required.)
The other way to do it is with a lambda function, which is mathematician speak for a nameless function you define on the fly.
The equivalent lambda function to the above OnFoundSomething function is:
So the only difference is that the function doesn't have a name, and the type of its return value and argument are worked out from the context in which you use it. As in:
With regard to your earlier attempt, I'm not certain but I suspect it may have been returning false all the time because you were iterating over all game objects, including the one you were testing; hence it would have been "colliding" with itself.