C# XNA 与 Farseer 物理中的 OnCollision 事件处理程序问题
我现在在我的游戏中运行得很好,但我的数学不太好。当两个基元碰撞时,如果施加到基元上的力超过设定的阈值,我希望它们粉碎成微小的碎片。我目前的碰撞事件处理程序如下所示。
public bool Collision(Fixture fixtureA, Fixture fixtureB, Manifold manifold)
{
Vector2 position = manifold.LocalNormal;
float angle = (float)Math.Atan2(position.Y, position.X);
Vector2 force = Vector2.Zero;
if (angle < 0)
force = new Vector2((float)(Math.Cos(angle) * fixtureA.Body.LinearVelocity.X), (float)Math.Sin(MathHelper.TwoPi + angle) * fixtureA.Body.LinearVelocity.Y);
else
force = new Vector2((float)(Math.Cos(angle) * fixtureA.Body.LinearVelocity.X), (float)Math.Sin(MathHelper.TwoPi - angle) * fixtureA.Body.LinearVelocity.Y);
double XForce = Math.Sqrt(force.X * force.X);
double YForce = Math.Sqrt(force.Y * force.Y);
double totalForce = XForce + YForce;
if ((Breakable) && (totalForce > BreakForce))
{
Breakable = false;
Active = false;
BreakUp(fixtureA, fixtureB);
}
return true;
}
很久以前,当我只是玩的时候,我就把它放在了。在某些情况下这会导致一些问题。例如,如果一个基元静止在地板上,而另一个基元从适当的高度跌落到其上,则几乎总是,坠落的盒子会爆炸,而静止的盒子会幸存。此外,如果两个盒子并排落下,并且彼此发生最微小的接触,那么两个盒子都会在半空中爆炸。嗯嗯,并不是很完美。有谁知道如何改进我的碰撞处理程序?提前致谢。
I have this working ok(ish) in my game at the moment, but i'm not fantastic at maths. When two primatives collide, I want them to smash up into tiny bits if the force applied to a primative was over a set threshold. My collision event handler at present looks like this.
public bool Collision(Fixture fixtureA, Fixture fixtureB, Manifold manifold)
{
Vector2 position = manifold.LocalNormal;
float angle = (float)Math.Atan2(position.Y, position.X);
Vector2 force = Vector2.Zero;
if (angle < 0)
force = new Vector2((float)(Math.Cos(angle) * fixtureA.Body.LinearVelocity.X), (float)Math.Sin(MathHelper.TwoPi + angle) * fixtureA.Body.LinearVelocity.Y);
else
force = new Vector2((float)(Math.Cos(angle) * fixtureA.Body.LinearVelocity.X), (float)Math.Sin(MathHelper.TwoPi - angle) * fixtureA.Body.LinearVelocity.Y);
double XForce = Math.Sqrt(force.X * force.X);
double YForce = Math.Sqrt(force.Y * force.Y);
double totalForce = XForce + YForce;
if ((Breakable) && (totalForce > BreakForce))
{
Breakable = false;
Active = false;
BreakUp(fixtureA, fixtureB);
}
return true;
}
I put that in a LONG time ago when I was just playing around. This causes a bit of a problem in certain situations. For example, if a primative is stationary on the floor and another primative falls onto it from a decent height, almost always, the falling box blows up and the resting box survives. Also if two boxes are falling side by side and give each other the tinyest of touches, then both boxes blow up mid air. Hmmmmm, not really perfect that. Does anyone have any idea how to improve my collision handler? Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
好的,我的其他答案 是可行的。但我更仔细地研究了 Farseer 3.0(当前的 SVN 版本),发现它已经实现几乎正是您想要做的事情。
查找“BreakableBody.cs”。您也许可以直接使用它 - 但否则您可以直接复制您想要的功能。
具体来说:您不想将一个函数附加到您的装置的
OnCollision
上,而是希望将一个函数附加到PostSolve
上。它需要一个ContactConstraint
,您可以深入研究它并找到碰撞产生的脉冲。这是
BreakableBody
使用的该函数的实现:显然流形中的脉冲数据仅在
PostSolve
中正确设置,而不是在OnCollision
中设置。Ok, so my other answer is viable. But I've looked at Farseer 3.0 (the current SVN version) more closely and found that it already implements almost exactly what you are trying to do.
Look for "BreakableBody.cs". You may be able to directly use that - but otherwise you could just copy out the functionality you want.
Specifically: Instead of attaching a function to your fixture's
OnCollision
you want to attach one toPostSolve
. It takes aContactConstraint
which you can dive into and find the impulses from the collision.This is the implementation of that function used by
BreakableBody
:Apparently the impulse data in the manifolds is only set correctly in
PostSolve
, not inOnCollision
.(虽然这是目前公认的答案 - 我会引导任何人到我的 其他答案可能是更好的方法。)
您对冲击力的计算完全错误。您需要获得接触点处的相对速度 - 您会得到一些非常奇怪的东西...
您的代码看起来像是使用 Farseer 3.0 (您应该指定,因为这更像是 Box2DX 的分支,而不是 Farseer 2.1) 。我在 Farseer 2.1(其中有
ContactList 联系人
而不是Manifold
)中获取撞击速度的方法是:从对 Farseer 3.0 源代码的简要查看来看,看来
Manifold
有一个成员:并且
Manifold
和ManifoldPoint
都有成员:修改我的 Farseer 2.1 代码来使用应该相当简单那些代替。
另外:我建议简单地将两个对象标记为需要破坏,然后在物理更新完成运行后(而不是在碰撞处理程序中)实际破坏它们。
(While this is currently the accepted answer - I would direct anyone to my other answer for a potentially superior approach.)
Your calculation of impact force is completely wrong. You need to get the relative velocity at the contact point(s) - you're getting something quite strange...
Your code looks like it's using Farseer 3.0 (you should specify, because that's more of a fork of Box2DX than Farseer 2.1). What I did in Farseer 2.1 (where you've got
ContactList contacts
instead of aManifold
) to get the impact velocity was:From a brief look at the Farseer 3.0 source, it seems that
Manifold
has a member:And both
Manifold
andManifoldPoint
have members:It should be fairly simple to modify my Farseer 2.1 code to use those instead.
Also: I recommend simply marking the two objects as needing to break, and then actually breaking them after your physics update finishes running (rather than in the collision handler).
我没有使用过 XNA,但作为一个物理问题,为什么不直接从 B 的线速度中减去 A 的线速度,并得到“力”作为结果向量的平方(将分量的平方相加) ?对于一个非常简单的物理模型,这应该与根据“E=(mv^2)/2”所涉及的动能相协调,即使我们忽略了质量(或者,就此而言,弹性或能量和能量之间的区别)势头)。如果物体以相同的速度沿相同的方向移动,您将得到一个较小的值;反之,您将得到一个较小的值。如果一个人高速接近(或者,当然,离开!),你会得到一个很大的值。
I haven't used XNA, but as a physics problem, why not just subtract the linear velocity of A from the linear velocity of B, and get the 'force' as the square of the resulting vector (sum the squares of the components)? That should harmonize with the kinetic energy involved according to `E=(mv^2)/2', for a very simple physical model, even if we are ignoring the masses (or, for that matter, elasticity or the distinction between energy and momentum). If the objects are moving in the same general direction at the same speed, you get a small value; if one is approaching (or, of course, departing!) at high speed, you get a large value.