在我的程序中,我有一个管道,其中一些圆形颗粒从左向右移动。我应该能够在管道中放置一些障碍物并且必须找到颗粒 绕过它的方式。我试图通过碰撞来实现这一点。
我的问题是,有些粒子进入我的障碍物(管道也是一个障碍物)并留在那里。 Image
我的代码在每个更新周期运行如下:
public void CheckCollisions()
{
// Variables
bool blnCollisionOccured = false;
Vector2 v2OldPosition;
// Go through particles
for (int i = 0; i < lstParticles.Count; i++)
{
// Move particle
v2OldPosition = lstParticles[i].v2Position;
lstParticles[i].v2Position += lstParticles[i].v2Speed;
// Check all obstacles
for (int j = 0; j < lstObstacles.Count; j++)
{
if (lstObstacles[j].GetType() == typeof(oRectangle))
{
blnCollisionOccured = CheckCollisionRectangle(lstParticles[i], (oRectangle)lstObstacles[j]);
}
else if (lstObstacles[j].GetType() == typeof(oCircle))
{
blnCollisionOccured = CheckCollisionCircle(lstParticles[i], (oCircle)lstObstacles[j]);
}
/* else if (lstObstacles[j].GetType() == typeof(oTriangle))
{
blnCollisionOccured = CheckCollisionTriangle(lstParticles[i], new oTriangle(lstObstacles[j]));
} */
}
// Check all particles
if (i != lstParticles.Count - 1)
{
for (int j = i + 1; j < lstParticles.Count; j++)
{
blnCollisionOccured = CheckCollisionParticle(lstParticles[i], lstParticles[j]);
}
}
// If collision, go back and add new speed (no hanging inside objects)
if (blnCollisionOccured)
{
lstParticles[i].v2Position = v2OldPosition;
lstParticles[i].v2Position += lstParticles[i].v2Speed;
}
}
}
private bool CheckCollisionRectangle(Particle p, oRectangle o)
{
// Check Collision
if (p.GetRectancle().Intersects(o.GetRectangle()))
{
Vector2[] v2Corners = o.GetCorners();
// Go through corners and check collision with corner
for (int i = 0; i < v2Corners.Length; i++)
{
if (Vector2.Distance(p.GetCenterPoint(), v2Corners[i]) < p.GetRadius())
{
Vector2 normal = v2Corners[i] - p.GetCenterPoint();
normal.Normalize();
p.v2Speed = Vector2.Reflect(p.v2Speed, normal);
return true;
}
}
// Go through corners to check lines between 2 corners
for (int i = 0; i < v2Corners.Length; i++)
{
// Save 2nd corner
Vector2 v2Corner2;
// If not last corner
if (i != v2Corners.Length - 1)
{
// Next corner
v2Corner2 = v2Corners[i + 1];
}
else
{
// First corner
v2Corner2 = v2Corners[0];
}
// Check collision
if (DistanceToLine(p.GetCenterPoint(), v2Corners[i], v2Corner2) <= p.GetRadius())
{
Vector2 normal = RightAngle(v2Corners[i] - v2Corner2);
normal.Normalize();
p.v2Speed = Vector2.Reflect(p.v2Speed, normal);
return true;
}
}
}
return false;
}
private bool CheckCollisionCircle(Particle p, oCircle o)
{
// Check Collision
if (Vector2.Distance(p.GetCenterPoint(), o.GetCenterPoint()) <= p.GetRadius() + o.GetRadius())
{
Vector2 normal = o.GetCenterPoint() - p.GetCenterPoint();
normal.Normalize();
p.v2Speed = Vector2.Reflect(p.v2Speed, normal);
return true;
}
return false;
}
private bool CheckCollisionParticle(Particle p1, Particle p2)
{
// Check Collision
if (Vector2.Distance(p1.GetCenterPoint(), p2.GetCenterPoint()) <= p1.GetRadius() + p2.GetRadius())
{
// Source: http://stackoverflow.com/questions/6216884/how-does-this-bouncing-off-object-after-collision-detection-code-work
Vector2 cOfMass = (p1.v2Speed + p2.v2Speed) / 2;
Vector2 normal1 = p2.GetCenterPoint() - p1.GetCenterPoint();
normal1.Normalize();
Vector2 normal2 = p1.GetCenterPoint() - p2.GetCenterPoint();
normal2.Normalize();
p1.v2Speed -= cOfMass;
p1.v2Speed = Vector2.Reflect(p1.v2Speed, normal1);
p1.v2Speed += cOfMass;
p2.v2Speed -= cOfMass;
p2.v2Speed = Vector2.Reflect(p2.v2Speed, normal2);
p2.v2Speed += cOfMass;
return true;
}
return false;
}
private Vector2 RightAngle(Vector2 v2)
{
return new Vector2(v2.Y, -v2.X);
}
// Distance vector to line Source: http://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
private double DistanceToLine(Vector2 point, Vector2 corner1, Vector2 corner2)
{
// Source: http://geomalgorithms.com/a02-_lines.html
//return ((corner1.Y - corner2.Y) * point.X + (corner2.X - corner1.X) * point.Y + (corner1.X * corner2.Y - corner2.X * corner1.Y)) / Math.Sqrt(Math.Pow(corner2.X - corner1.X, 2) + Math.Pow(corner2.Y - corner1.Y, 2));
float l2 = Vector2.DistanceSquared(corner1, corner2);
if (l2 == 0) return (float)Math.Sqrt(Vector2.DistanceSquared(point, corner1));
float t = ((point.X - corner1.X) * (corner2.X - corner1.X) + (point.Y - corner1.Y) * (corner2.Y - corner1.Y)) / l2;
if (t < 0) return (float)Math.Sqrt(Vector2.DistanceSquared(point, corner1));
if (t > 1) return (float)Math.Sqrt(Vector2.DistanceSquared(point, corner2));
return (float)Math.Sqrt(Vector2.DistanceSquared(point, new Vector2(corner1.X + t * (corner2.X - corner1.X), corner1.Y + t * (corner2.Y - corner1.Y))));
}
我希望你能以某种方式帮助我找到解决方案。