[英]How to resolve a 2D collision with an immovable object?
I am creating a 2D physics engine, and I am having trouble with a certain type of collision between movable and immovable objects. 我正在创建一个2D物理引擎,我遇到了可移动和不可移动物体之间某种类型的碰撞问题。 What I mean by movable is that the (x,y) values can change, not that the frame of reference can or can't change. 我的意思是可移动的是(x,y)值可以改变,而不是参考框架可以改变或不改变。
For example, a ball hitting a wall would be something that is movable colliding with something immovable. 例如,击中墙壁的球将是可移动的与可移动的东西碰撞的东西。
I believe that I need to use something like Normal Force in this situation, but I am no sure how that would be used for finding the outcome of the collision. 我认为在这种情况下我需要使用类似法向力的东西,但我不确定如何用它来找到碰撞的结果。
Here is the code that I have so far. 这是我到目前为止的代码。 This code is for collision between two moving entities, but I need to add a case for when one is not moving: 此代码用于两个移动实体之间的冲突,但我需要添加一个不移动的情况:
private static void UpdateEntities(PhysicsEntity a, PhysicsEntity b)
{
var collisionAngle = Math.Atan2(a.Position.Y - b.Position.Y, a.Position.X - b.Position.X);
var angleA = a.Velocity.Direction - collisionAngle;
var angleB = b.Velocity.Direction - collisionAngle;
var vAx = a.Velocity.Magnitude * Math.Cos(angleA);
var vAy = a.Velocity.Magnitude * Math.Sin(angleA);
var vBx = b.Velocity.Magnitude * Math.Cos(angleB);
var vBy = b.Velocity.Magnitude * Math.Sin(angleB);
var vfAx = ((vAx * (a.Mass - b.Mass) + 2 * b.Mass * vBx) / (a.Mass + b.Mass)) * a.Material.Elasticity;
var vfBx = ((vBx * (b.Mass - a.Mass) + 2 * a.Mass * vAx) / (a.Mass + b.Mass)) * b.Material.Elasticity;
var vfAy = vAy * a.Material.Elasticity;
var vfBy = vBy * b.Material.Elasticity;
var magA = Math.Sqrt(Math.Pow(vfAx, 2) + Math.Pow(vfAy, 2));
var magB = Math.Sqrt(Math.Pow(vfBx, 2) + Math.Pow(vfBy, 2));
var dirA = Math.Atan2(vfAy, vfAx) + collisionAngle;
var dirB = Math.Atan2(vfBy, vfBx) + collisionAngle;
a.Velocity.X = magA * Math.Cos(dirA);
a.Velocity.Y = magA * Math.Sin(dirA);
b.Velocity.X = magB * Math.Cos(dirB);
b.Velocity.Y = magB * Math.Sin(dirB);
}
I tried setting the velocity of the immovable object to the opposite of the movable object's velocity, but that caused things to phase into each other. 我尝试将不可移动物体的速度设置为与可移动物体的速度相反,但这导致物体彼此相位相交。
I was able to get help from a friend and we worked out this algorithm to have objects reflect off of immovable objects during a collision. 我能够得到朋友的帮助,我们制定了这个算法,让物体在碰撞过程中反射出不可移动的物体。
Modified Original Function: 修改原始功能:
private static void UpdateEntities(PhysicsEntity a, PhysicsEntity b)
{
var collisionAngle = Math.Atan2(a.Position.Y - b.Position.Y, a.Position.X - b.Position.X);
if (a.IsMoveable && b.IsMoveable)
{
var angleA = a.Velocity.Direction - collisionAngle;
var angleB = b.Velocity.Direction - collisionAngle;
var vAx = a.Velocity.Magnitude * Math.Cos(angleA);
var vAy = a.Velocity.Magnitude * Math.Sin(angleA);
var vBx = b.Velocity.Magnitude * Math.Cos(angleB);
var vBy = b.Velocity.Magnitude * Math.Sin(angleB);
var vfAx = ((vAx * (a.Mass - b.Mass) + 2 * b.Mass * vBx) / (a.Mass + b.Mass)) * a.Material.Elasticity;
var vfBx = ((vBx * (b.Mass - a.Mass) + 2 * a.Mass * vAx) / (a.Mass + b.Mass)) * b.Material.Elasticity;
var vfAy = vAy * a.Material.Elasticity;
var vfBy = vBy * b.Material.Elasticity;
var magA = Math.Sqrt(Math.Pow(vfAx, 2) + Math.Pow(vfAy, 2));
var magB = Math.Sqrt(Math.Pow(vfBx, 2) + Math.Pow(vfBy, 2));
var dirA = Math.Atan2(vfAy, vfAx) + collisionAngle;
var dirB = Math.Atan2(vfBy, vfBx) + collisionAngle;
a.Velocity.X = magA * Math.Cos(dirA);
a.Velocity.Y = magA * Math.Sin(dirA);
b.Velocity.X = magB * Math.Cos(dirB);
b.Velocity.Y = magB * Math.Sin(dirB);
}
else
{
var sign = Math.Sign(collisionAngle);
collisionAngle *= sign;
while (collisionAngle > Math.PI/2)
{
collisionAngle -= Math.PI / 2;
}
collisionAngle *= sign;
if (a.IsMoveable)
{
Reflection(ref a, b, collisionAngle);
}
else
{
Reflection(ref b, a, collisionAngle);
}
}
}
Reflection Function: 反射功能:
private static void Reflection(ref PhysicsEntity movable, PhysicsEntity immovable, double collisionAngle)
{
if (Math.Abs(collisionAngle - Math.PI / 2) < Universe.Epsilon)
{
// take the velocity vector, rotate it 180 degrees, scale it
movable.Velocity.X *= -1;
movable.Velocity.Y *= -1;
}
else if (Math.Abs(movable.Position.Y - immovable.Position.Y) < Universe.Epsilon ||
(movable.Position.X > movable.CollisionPoint.X ^ movable.Position.Y < movable.CollisionPoint.Y))
{
//take velocity vector, rotate CCW by 2*collisionAngle, scale it
var rotateAngle = 2 * collisionAngle;
var xPrime = movable.Velocity.X * Math.Cos(rotateAngle) - movable.Velocity.Y * Math.Sin(rotateAngle);
var yPrime = movable.Velocity.Y * Math.Cos(rotateAngle) - movable.Velocity.X * Math.Sin(rotateAngle);
movable.Velocity.X = xPrime;
movable.Velocity.Y = yPrime;
}
else
{
//take the vector, rotate it CCW by 360-2*collisionAngle, scale it
var rotateAngle = 2 * (Math.PI - collisionAngle);
var xPrime = movable.Velocity.X * Math.Cos(rotateAngle) - movable.Velocity.Y * Math.Sin(rotateAngle);
var yPrime = movable.Velocity.Y * Math.Cos(rotateAngle) - movable.Velocity.X * Math.Sin(rotateAngle);
movable.Velocity.X = xPrime;
movable.Velocity.Y = yPrime;
}
movable.Velocity.X *= movable.Material.Elasticity;
movable.Velocity.Y *= movable.Material.Elasticity;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.