Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 二维弹性碰撞&x27;粘滞';问题_C#_2d_Collision Detection_Collision - Fatal编程技术网

C# 二维弹性碰撞&x27;粘滞';问题

C# 二维弹性碰撞&x27;粘滞';问题,c#,2d,collision-detection,collision,C#,2d,Collision Detection,Collision,我有一个在2D空间中移动多个圆的模拟 它们之间有碰撞检测,弹性碰撞在95%的时间内工作。然而,偶尔,当两个球相互撞击时,它们会相互粘着并重叠,通常在粘着在一起的同时围绕彼此旋转 我不知道如何解决这个问题 我的冲突管理功能如下所示: void manageCollision(Particle particleA, Particle particleB) { float distanceX = particleA.Position.X - particleB.Position.X;

我有一个在2D空间中移动多个圆的模拟

它们之间有碰撞检测,弹性碰撞在95%的时间内工作。然而,偶尔,当两个球相互撞击时,它们会相互粘着并重叠,通常在粘着在一起的同时围绕彼此旋转

我不知道如何解决这个问题

我的冲突管理功能如下所示:

void manageCollision(Particle particleA, Particle particleB)
{
    float distanceX = particleA.Position.X - particleB.Position.X;
    float distanceY = particleA.Position.Y - particleB.Position.Y;
    double collisionAngle = Math.Atan2(distanceY, distanceX);
    double pA_magnitude = Math.Sqrt(particleA.Velocity.X * particleA.Velocity.X + particleA.Velocity.Y * particleA.Velocity.Y);
    double pB_magnitude = Math.Sqrt(particleB.Velocity.X * particleB.Velocity.X + particleB.Velocity.Y * particleB.Velocity.Y);
    double pA_direction = Math.Atan2(particleA.Velocity.Y, particleA.Velocity.X);
    double pB_direction = Math.Atan2(particleB.Velocity.Y, particleB.Velocity.X);
    double pA_newVelocityX = pA_magnitude * Math.Cos(pA_direction - collisionAngle);
    double pA_newVelocityY = pA_magnitude * Math.Sin(pA_direction - collisionAngle);
    double pB_newVelocityX = pB_magnitude * Math.Cos(pB_direction - collisionAngle);
    double pB_newVelocityY = pB_magnitude * Math.Sin(pB_direction - collisionAngle);
    double pA_finalVelocityX = ((particleA.Mass - particleB.Mass) * pA_newVelocityX + (particleB.Mass + particleB.Mass) * pB_newVelocityX) / (particleA.Mass + particleB.Mass);
    double pB_finalVelocityX = ((particleA.Mass + particleA.Mass) * pA_newVelocityX + (particleB.Mass - particleA.Mass) * pB_newVelocityX) / (particleA.Mass + particleB.Mass);
    double pA_finalVelocityY = pA_newVelocityY;
    double pB_finalVelocityY = pB_newVelocityY;
    particleA.Velocity = new Vector2((float)(Math.Cos(collisionAngle) * pA_finalVelocityX + Math.Cos(collisionAngle + Math.PI / 2) * pA_finalVelocityY), (float)(Math.Sin(collisionAngle) * pA_finalVelocityX + Math.Sin(collisionAngle + Math.PI / 2) * pA_finalVelocityY));
    particleB.Velocity = new Vector2((float)(Math.Cos(collisionAngle) * pB_finalVelocityX + Math.Cos(collisionAngle + Math.PI / 2) * pB_finalVelocityY), (float)(Math.Sin(collisionAngle) * pB_finalVelocityX + Math.Sin(collisionAngle + Math.PI / 2) * pB_finalVelocityY));
}
Particle pA = particles[i];
for (int k = i + 1; k < particles.Count(); k++)
{
    Particle pB = particles[k];
    Vector2 delta = pA.Position - pB.Position;
    float dist = delta.Length();

    if (dist < particles[i].Radius + particles[k].Radius && !particles[i].Colliding && !particles[k].Colliding)
    {
        particles[i].Colliding = true;
        particles[k].Colliding = true;
        manageCollision(particles[i], particles[k]);
        particles[i].initColorTable(); // Upon collision, change the color
        particles[k].initColorTable();
        totalCollisions++;
    }
    else
    {
        particles[i].Colliding = false;
        particles[k].Colliding = false;
    }
}
每个球或粒子以随机质量和半径繁殖

函数在更新类型的方法中调用,如下所示:

void manageCollision(Particle particleA, Particle particleB)
{
    float distanceX = particleA.Position.X - particleB.Position.X;
    float distanceY = particleA.Position.Y - particleB.Position.Y;
    double collisionAngle = Math.Atan2(distanceY, distanceX);
    double pA_magnitude = Math.Sqrt(particleA.Velocity.X * particleA.Velocity.X + particleA.Velocity.Y * particleA.Velocity.Y);
    double pB_magnitude = Math.Sqrt(particleB.Velocity.X * particleB.Velocity.X + particleB.Velocity.Y * particleB.Velocity.Y);
    double pA_direction = Math.Atan2(particleA.Velocity.Y, particleA.Velocity.X);
    double pB_direction = Math.Atan2(particleB.Velocity.Y, particleB.Velocity.X);
    double pA_newVelocityX = pA_magnitude * Math.Cos(pA_direction - collisionAngle);
    double pA_newVelocityY = pA_magnitude * Math.Sin(pA_direction - collisionAngle);
    double pB_newVelocityX = pB_magnitude * Math.Cos(pB_direction - collisionAngle);
    double pB_newVelocityY = pB_magnitude * Math.Sin(pB_direction - collisionAngle);
    double pA_finalVelocityX = ((particleA.Mass - particleB.Mass) * pA_newVelocityX + (particleB.Mass + particleB.Mass) * pB_newVelocityX) / (particleA.Mass + particleB.Mass);
    double pB_finalVelocityX = ((particleA.Mass + particleA.Mass) * pA_newVelocityX + (particleB.Mass - particleA.Mass) * pB_newVelocityX) / (particleA.Mass + particleB.Mass);
    double pA_finalVelocityY = pA_newVelocityY;
    double pB_finalVelocityY = pB_newVelocityY;
    particleA.Velocity = new Vector2((float)(Math.Cos(collisionAngle) * pA_finalVelocityX + Math.Cos(collisionAngle + Math.PI / 2) * pA_finalVelocityY), (float)(Math.Sin(collisionAngle) * pA_finalVelocityX + Math.Sin(collisionAngle + Math.PI / 2) * pA_finalVelocityY));
    particleB.Velocity = new Vector2((float)(Math.Cos(collisionAngle) * pB_finalVelocityX + Math.Cos(collisionAngle + Math.PI / 2) * pB_finalVelocityY), (float)(Math.Sin(collisionAngle) * pB_finalVelocityX + Math.Sin(collisionAngle + Math.PI / 2) * pB_finalVelocityY));
}
Particle pA = particles[i];
for (int k = i + 1; k < particles.Count(); k++)
{
    Particle pB = particles[k];
    Vector2 delta = pA.Position - pB.Position;
    float dist = delta.Length();

    if (dist < particles[i].Radius + particles[k].Radius && !particles[i].Colliding && !particles[k].Colliding)
    {
        particles[i].Colliding = true;
        particles[k].Colliding = true;
        manageCollision(particles[i], particles[k]);
        particles[i].initColorTable(); // Upon collision, change the color
        particles[k].initColorTable();
        totalCollisions++;
    }
    else
    {
        particles[i].Colliding = false;
        particles[k].Colliding = false;
    }
}
粒子pA=粒子[i];
对于(int k=i+1;k
这种情况源于离散计算和大步长的持续时间

当观察具有某个时间间隔dt的对象时,可以观察两个圆之间的某些交点并调用碰撞方法,但在下一个时间步骤中,它们可能仍然重叠,尽管它们在上一个步骤中发生碰撞后朝不同的方向移动

若要减少此效果,可以尝试使用较低的时间步长,以便降低对象之间的重叠率。 作为一个更复杂的解决方案,您可以为每个步骤保留一个碰撞对象的列表,并且在迭代过程中,如果当前相交圆在上一步中有任何“事件”,您可以检查此列表