XNA碰撞检测 - Vector2.Reflect - 如何计算圆形精灵的法向量 - C#

3
我对如何计算在2D空间中移动的圆的法线感到困惑。我已经知道需要计算对象速度(方向速度)的法线,但是我的大学代数思维已经超载了。我正在处理两个2D圆,它们具有中心点、半径、速度和位置。
最终,我想使用Vector2.Reflect方法来获得更真实的物理效果。
提前致谢。
编辑:添加了一些代码尝试建议(没有成功),可能会误解建议。这里我使用篮球和棒球,因此有base和basket。我还有位置和速度,将其添加到位置以创建移动。
if ((Vector2.Distance(baseMid, basketMid)) < baseRadius + basketRadius)
{
    Vector2 baseNorm = basketMid - baseMid;
    baseNorm.Normalize();
    Vector2 basketNorm = baseMid - basketMid;
    basketNorm.Normalize();
    baseVelocity = Vector2.Reflect(baseVelocity, baseNorm);
    basketVelocity = Vector2.Reflect(basketVelocity, basketNorm);
}

basePos.Y += baseVelocity.Y;
basePos.X += baseVelocity.X;
basketPos.Y += basketVelocity.Y;
basketPos.X += basketVelocity.X;
basketMid = new Vector2((basketballTex.Width / 2 + basketPos.X), (basketballTex.Height / 2 + basketPos.Y));
baseMid = new Vector2((baseballTex.Width / 2 + basePos.X), (baseballTex.Height / 2 + basePos.Y));
3个回答

5
首先是反射。如果我正确地阅读了您的代码,Vector2.Reflect的第二个参数是表面的法线。水平地板的法线为(0,1),当速度为(4,-3)的球撞击它并以速度(4,3)飞离时,是这样吗?如果不是这样,那么我们将不得不改变if语句的主体。(请注意,通过设置basketNorm = -baseNorm,您可以节省一些周期。)
现在是物理学。按照现有写法,当两个球碰撞时,每个球都会像撞到两个球体的切线上的玻璃墙一样弹开,这并不现实。想象打台球:一个快速的红球正中击中一个静止的蓝球。红球会反弹并使蓝球保持原位吗?不,蓝球会被击退,并且红球失去了大部分速度(在完美情况下全部)。再看一个炮弹和一个高尔夫球,它们以相同的速度但相反的方向移动,头对头碰撞。它们都会同样反弹吗?不,炮弹会继续前进,几乎没有感觉到冲击,但是高尔夫球会反向飞出比来时更快。
要理解这些碰撞,您必须了解动量(如果您想要非完全弹性的碰撞,例如豆袋相撞时,您还必须了解能量)。基本的物理教科书将在早期章节中涵盖这一点。如果您只想能够模拟这些事情,请使用质心系:
Vector2 CMVelocity = (basket.Mass*basket.Velocity + base.Mass*base.Velocity)/(basket.Mass + base.Mass);
baseVelocity -= CMVelocity; baseVelocity = Vector2.Reflect(baseVelocity, baseNorm); baseVelocity += CMVelocity;
basketVelocity -= CMVelocity; basketVelocity = Vector2.Reflect(basketVelocity, basketNorm); basketVelocity += CMVelocity;

我非常感谢您的补充,但问题在于问题中的代码无法运行。在上述代码能够正常工作之前,我无法尝试添加Mass。 - user48202
你能说的更具体一些吗?它是无法编译吗?如果球靠近时 if 语句未触发,或者当球分开时触发了吗? 球没有直线运动吗?它们会以奇怪的方式弹跳吗?(并且这是C++,对吧?) - Beta
抱歉,我的错。当我将它转换为GPU上的计算着色器时,我删除了质量计算,因此在CMVelocity末尾删除了乘以* .5的操作。对此感到抱歉。 - zezba9000

1

在圆的边缘给定点处的法线将是从其中心到该点的方向。假设您正在处理圆形碰撞,则一种简单的“速记”方法是,在碰撞发生时(当圆相互接触时)以下内容将成立:

令A为一个圆的中心,B为另一个圆的中心。圆A的法线将是normalize(B-A),圆B的法线将是normalize(A-B)。这是正确的,因为它们接触的点始终与两个圆的中心共线。


我将在原始问题中添加一些代码,以说明我想要实现的内容。谢谢,我知道实际上逻辑上什么是法线,但仍不清楚如何计算它,以及应该将哪个向量放在Vector2.Reflect的第一个插槽中。抱歉,当涉及到这些东西时,我有点迟钝。 - user48202

0

注意:我不会假设这完全正确。物理学不是我的专长。

运动对法线没有影响。通常,法线只是一个标准化(长度为1)的向量,指示3D对象上多边形面朝的方向。

我认为你想做的是找到两个圆之间的碰撞法线,是吗?如果是这样,球体的一个很酷的特性是,如果你找到它们中心之间的距离,你可以将其标准化以获得球体的法线。

对于2D物理学来说,似乎正确的方法是,将球体的速度*质量(能量)乘以另一个球体的标准化向量。将结果添加到目标球体的能量中,从原始球体的能量中减去它,并分别除以质量以获得结果速度。如果另一个球体在移动,则反向执行相同的操作。当然,你可以简化数学计算,但现在已经很晚了,我不想做了 :)

如果两个球体都在移动,则为另一个球体重复该过程(尽管你可能可以简化该方程以获得更有效的数学计算)。

这只是草稿纸上的数学计算,但它似乎给出了正确的结果。嘿,我曾经自己推导欧拉角,所以有时我的草稿纸上的数学计算确实能得出正确的结果。

这也假设碰撞是完全弹性的。

如果我错了,我很乐意找出原因 :)


嗯,物理有点是我的专长,虽然我很欣赏你的创造力,但你犯了一些错误。首先,你似乎在将向量加到标量(无方向量)中,这在传统上是不允许的。下一句话不清楚(加到这个,从那个减去,然后每个除以...啥?),似乎可以简化为A-(A+B)。这只能在一些非常特殊的情况下起作用。如果你想玩得开心,可以尝试一些1D碰撞,就像我回答中的例子一样,并尝试找到一种有效的方法。没有什么比解决自然之谜更有趣的了! - Beta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接