2D 공간에서 움직이는 여러 개의 원이있는 시뮬레이션이 있습니다.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;
}
}