C# xna4.0中的碰撞响应和弹性冲量
我知道C#或XNA有物理插件,但我想创建自己的插件,这样我就可以了解这个主题 我的问题如下: 我试图以正确的角度和速度给我的角色施加一个弹性脉冲。速度的计算方法正确,角度不正确,结果会扭曲! 下一个问题是,我的角色进入了摇晃模式,尽管它应该静止不动。我知道问题从哪里来,但是我不知道如何修复它(编辑:我必须考虑它的穿透深度吗?)< /P>C# xna4.0中的碰撞响应和弹性冲量,c#,xna,physics,collision,C#,Xna,Physics,Collision,我知道C#或XNA有物理插件,但我想创建自己的插件,这样我就可以了解这个主题 我的问题如下: 我试图以正确的角度和速度给我的角色施加一个弹性脉冲。速度的计算方法正确,角度不正确,结果会扭曲! 下一个问题是,我的角色进入了摇晃模式,尽管它应该静止不动。我知道问题从哪里来,但是我不知道如何修复它(编辑:我必须考虑它的穿透深度吗?)< /P> IPhysicsObject继承了最重要的信息,Vector2[]的碰撞点位于索引0,穿透深度位于索引1 我试着和你一起工作,但是是的。。我不知道 pu
IPhysicsObject
继承了最重要的信息,Vector2[]
的碰撞点位于索引0,穿透深度位于索引1
我试着和你一起工作,但是是的。。我不知道
public void ElasticImpulse(IPhysicsObject Object, Vector2[] _colPos)
{
//this function is down below
if (checkCollidingObjects(m_cCharacter, Object))
return;
//this List is like this declined:
//public static List<IPhysicsObject[]> CollidingObjects = new List<IPhysicsObject[]>();
//this list contains every pair of objects, that collided this frame, it is cleared after all physics and game logic is done.
CollidingObjects.Add(new IPhysicsObject[] { m_cCharacter, Object });
//deltavelocity is the velocity between two frames
Vector2 v1 = Velocity - DeltaVelocity;
float lv1 = (float)Math.Sqrt(v1.X * v1.X + v1.Y * v1.Y);
float m1 = Mass;
float k1 = Damping;
Vector2 v2 = Object.Physik.Velocity - Object.Physik.DeltaVelocity;
float lv2 = (float)Math.Sqrt(v2.X * v2.X + v2.Y * v2.Y);
float m2 = Object.Mass;
float k2 = Object.Physik.Damping;
Vector2 colDir1 = _colPos[0] - m_cCharacter.Position;
Vector2 colDir2 = _colPos[0] - Object.Position;
colDir1.Normalize();
colDir2.Normalize();
Vector2 colNorm1 = new Vector2(colDir1.Y, -colDir1.X);
Vector2 colNorm2 = new Vector2(colDir2.Y, -colDir2.X);
float ldir1 = (float)Math.Sqrt(colNorm1.X * colNorm1.X + colNorm1.Y * colNorm1.Y);
float ldir2 = (float)Math.Sqrt(colNorm2.X * colNorm2.X + colNorm2.Y * colNorm2.Y);
float pi = MathHelper.Pi;
//float angle1 = pi - ((v1.X * colNorm1.X + v2.Y * colNorm1.Y) / (lv1 * ldir1)) / v1.Length();
float angle1 = pi - (float)Math.Acos(((v1.X * colNorm1.X + v2.Y * colNorm1.Y) / (lv1 * ldir1)) / v1.Length());
angle1 = (float.IsNaN(angle1)) ? 0 : angle1;
//float angle2 = pi - ((v2.X * colNorm2.X + v2.Y * colNorm2.Y) / (lv2 * ldir1)) / v2.Length();
float angle2 = pi - (float)Math.Acos(((v2.X * colNorm2.X + v2.Y * colNorm2.Y) / (lv2 * ldir1)) / v2.Length());
angle2 = (float.IsNaN(angle2)) ? 0 : angle2;
//calculating the new velocities u 1/2. Got this formula out of the wiki link i posted above (took the german wiki version)
Vector2 u1 = (m1 * v1 + m2 * v2 - (m2 * (v1 - v2) * k2)) / (m1 + m2) - v1;
Vector2 u2 = (m1 * v1 + m2 * v2 - (m1 * (v2 - v1) * k1)) / (m1 + m2) - v2;
//transform the new velocities by the correct angle
Vector2 newV1 = new Vector2(
u1.X * (float)Math.Cos(angle1) - u1.Y * (float)Math.Sin(angle1),
u1.X * (float)Math.Sin(angle1) + u1.Y * (float)Math.Cos(angle1));
Vector2 newV2 = new Vector2(
u2.X * (float)Math.Cos(angle2) - u2.Y * (float)Math.Sin(angle2),
u2.X * (float)Math.Sin(angle2) + u2.Y * (float)Math.Cos(angle2));
newV1 = new Vector2(
(float.IsNaN(newV1.X)) ? 0 : newV1.X,
(float.IsNaN(newV1.Y)) ? 0 : newV1.Y);
newV2 = new Vector2(
(float.IsNaN(newV2.X)) ? 0 : newV2.X,
(float.IsNaN(newV2.Y)) ? 0 : newV2.Y);
AddForce(newV1);
Object.Physik.AddForce(newV2);
}
bool checkCollidingObjects(IPhysicsObject obj1, IPhysicsObject obj2)
{
if (CollidingObjects.Count > 0)
{
int a = CollidingObjects.FindIndex(x => (x[0] == obj1 && x[1] == obj2) ||
(x[1] == obj1 && x[0] == obj2));
return a != -1;
}
return false;
}
public void ElasticImpulse(IPhysicsObject对象,矢量2[]\u colPos)
{
//这个函数在下面
if(检查碰撞对象(m_字符,对象))
返回;
//此列表如下所示:
//public static List collingobjects=new List();
//此列表包含与此帧碰撞的每一对对象,在完成所有物理和游戏逻辑后,将清除该列表。
添加(新的IPhysicsObject[]{m_-cCharacter,Object});
//deltavelocity是两帧之间的速度
Vector2 v1=速度-三角速度;
float lv1=(float)Math.Sqrt(v1.X*v1.X+v1.Y*v1.Y);
浮球m1=质量;
浮球k1=阻尼;
Vector2 v2=Object.Physik.Velocity-Object.Physik.DeltaVelocity;
float lv2=(float)Math.Sqrt(v2.X*v2.X+v2.Y*v2.Y);
浮动m2=物体质量;
float k2=Object.Physik.Damping;
向量2 colDir1=\u colPos[0]-m\u cCharacter.Position;
Vector2 colDir2=_colPos[0]-对象位置;
colDir1.Normalize();
colDir2.Normalize();
Vector2 colNorm1=新的Vector2(colDir1.Y,-colDir1.X);
Vector2 colNorm2=新的Vector2(colDir2.Y,-colDir2.X);
float ldir1=(float)Math.Sqrt(colNorm1.X*colNorm1.X+colNorm1.Y*colNorm1.Y);
float ldir2=(float)Math.Sqrt(colNorm2.X*colNorm2.X+colNorm2.Y*colNorm2.Y);
float pi=MathHelper.pi;
//浮动角度1=pi-((v1.X*colNorm1.X+v2.Y*colNorm1.Y)/(lv1*ldir1))/v1.Length();
float angle1=pi-(float)Math.Acos(((v1.X*colNorm1.X+v2.Y*colNorm1.Y)/(lv1*ldir1))/v1.Length());
角度1=(float.IsNaN(angle1))?0:angle1;
//浮动角度2=pi-((v2.X*colNorm2.X+v2.Y*colNorm2.Y)/(lv2*ldir1))/v2.Length();
float angle2=pi-(float)Math.Acos((v2.X*colNorm2.X+v2.Y*colNorm2.Y)/(lv2*ldir1))/v2.Length();
角度2=(float.IsNaN(angle2))?0:angle2;
//计算新的速度u 1/2。从我上面发布的wiki链接中得到这个公式(以德语wiki版本为例)
向量2 u1=(m1*v1+m2*v2-(m2*(v1-v2)*k2))/(m1+m2)-v1;
向量2 u2=(m1*v1+m2*v2-(m1*(v2-v1)*k1))/(m1+m2)-v2;
//以正确的角度变换新速度
Vector2 newV1=新Vector2(
u1.X*(浮点)数学Cos(angle1)-u1.Y*(浮点)数学Sin(angle1),
u1.X*(float)Math.Sin(angle1)+u1.Y*(float)Math.Cos(angle1));
Vector2 newV2=新Vector2(
u2.X*(浮点)数学Cos(angle2)-u2.Y*(浮点)数学Sin(angle2),
u2.X*(float)Math.Sin(angle2)+u2.Y*(float)Math.Cos(angle2));
newV1=新矢量2(
(float.IsNaN(newV1.X))?0:newV1.X,
(float.IsNaN(newV1.Y))?0:newV1.Y);
newV2=新矢量2(
(float.IsNaN(newV2.X))?0:newV2.X,
(float.IsNaN(newV2.Y))?0:newV2.Y);
AddForce(newV1);
Object.Physik.AddForce(newV2);
}
布尔检查碰撞对象(IPhysicsObject对象J1、IPhysicsObject对象J2)
{
如果(CollingObjects.Count>0)
{
int a=collingobjects.FindIndex(x=>(x[0]==obj1&&x[1]==obj2)|
(x[1]==obj1&&x[0]==obj2));
返回a!=-1;
}
返回false;
}
我想你所说的震动是当一个物体为了它的方向而奋力挣扎时——比如当你的物体被重力向下拉动时,但是你的碰撞处理使它向上移动。是的,我知道。通常我只是取消了加入重力常数来阻止它。但我现在想做得更现实一点。我现在添加了一个反重力,如何抵消重力,使角色静止。我认为问题也在于脉冲函数。我的预测是它不会停止反弹。我想添加一个真实物理的简单版本。你可以说是最小化版本一般来说,如果可以避免的话,你不应该弄乱角度。在这种情况下,你可以。你能加一个碰撞的数字吗?不清楚变量代表什么(例如,DeltaVelocity
,colNorm1/2
,u
…)。如何从速度计算碰撞法线?这取决于身体的形状。或者您是否有标准对象(例如球体)?其中一具尸体是固定的还是都可以移动?震动可能是由多个碰撞引起的,其中应该只有一个碰撞(因此速度向量的多次反射)!这只是一个2D游戏,我只是在玩矩形。在我的测试中,现在我只得到了一个可移动的(我的角色)和他应该反弹的地面,但我希望尽可能保持它的通用性(对于敌人或物品反弹,idk)。我通过采用“float angle1=pi-(float)…”来解决角度问题,并将其转换为“float angle=Vector2.Dot(v1,colNorm1)/lv1;''th