2D 공간에서 움직이는 여러 원이있는 시뮬레이션이 있는데, 둘 사이에 탄성 충돌이 있습니다.2D 볼 사이의 끌어 당김 력
입자 사이에 인력을 추가하여 입자가 질량 등에 따라 다른 입자쪽으로 이동하도록하고 싶습니다. 어떻게해야합니까?
내 충돌 관리 기능은 다음과 같습니다
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));
}
각각의 볼 또는 입자가 임의의 질량과 반지름 생성합니다.
기능은 다음과 같이 방법의 업데이트 유형 내에서 호출됩니다
Vector2 globalGravity = new Vector2(0f, gravityScale/6000);
for (int i = 0; i < particles.Count(); i++)
{
particles[i].Update((float)updateTimer.Interval, globalGravity);
Vector2 position = particles[i].Position;
Vector2 velocity = particles[i].Velocity;
collisionWallCheck(ref position, ref velocity, particles[i].Radius);
particles[i].Position = position;
particles[i].Velocity = velocity;
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 updateTimer_Tick(object sender, EventArgs e)
{
const double G = 6.67398 * 0.00000000001;
for (int i = 0; i < particles.Count(); i++)
{
double sumX = 0;
double sumY = 0;
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();
particles[k].initColorTable();
totalCollisions++;
particles[i].Colliding = false;
particles[k].Colliding = false;
}
else
{
double distanceX = particles[i].Position.X - particles[k].Position.X;
double distanceY = particles[i].Position.Y - particles[k].Position.Y;
double r = Math.Sqrt(Math.Pow(distanceX, 2) + Math.Pow(distanceY, 2));
double force = G * particles[i].Mass * particles[k].Mass/(r * r);
double theta = Math.Tan(distanceY/distanceX);
sumX += force * Math.Cos(theta);
sumY += force * Math.Sin(theta);
particles[i].Colliding = false;
particles[k].Colliding = false;
}
}
double netForce = Math.Sqrt(Math.Pow(sumX, 2) + Math.Pow(sumY, 2));
double a = netForce/particles[i].Mass;
double aTheta = Math.Tan(sumY/sumX);
// Here we get accelerations for X and Y. You can probably figure out velocities from here.
double aX = a * Math.Cos(aTheta);
double aY = a * Math.Sin(aTheta);
Vector2 accel = new Vector2((float)aX, (float)aY);
particles[i].Update((float)updateTimer.Interval, accel);
//particles[i].Update((float)updateTimer.Interval, globalGravity);
Vector2 position = particles[i].Position;
Vector2 velocity = particles[i].Velocity;
collisionWallCheck(ref position, ref velocity, particles[i].Radius);
particles[i].Position = position;
particles[i].Velocity = velocity + accel;
}
Draw();
}
입자에 대한 업데이트 기능은 간단하며 0,0 인 전역 중력 벡터를 사용하기 전에 간단합니다.
public void Update(float timeStep, Vector2 gravity)
{
velocity = velocity + timeStep * gravity;
position = position + timeStep * velocity;
}
내가 위치 모든 공을 자신의 질량을 알면 0
아주 좋은 설명, 고맙습니다. 이 코드는 어디에 추가해야합니까? – Edge
코드를 삽입하는 것보다는 코드를 병합해야합니다. 내가 넣은 것들은 각 입자에 대한 중력 때문에 가속도를 계산합니다. 당신은 다른 힘 (충돌 등)으로 인한 가속에 그것을 추가하기를 원할 것입니다. 그런 다음 합계 된 가속도 (Vector2 여야 함)를 사용하여 새 속도를 결정한 다음 위치를 지정하십시오. 요점은 파티클이 어디에 위치하는지 계산을 분리해야한다는 것입니다. 배치에서 모든 것을 계산 한 다음 일괄 적으로 업데이트합니다. –
나는 당신의 제안을 구현하려고 시도했지만, 이제는 볼에 아무 것도 표시되지 않습니다. 내가 뭔가 잘못했다고 가정하고있어. – Edge