2013-03-08 105 views
1

我正在做一个关于robocup的学校项目,其中机器人正在与AI玩足球。由于一切工作正常,我仍然坚持一些东西。冲击点:圆形碰撞

机器人是从顶视图中绘制的简单球体。不应允许双方进入对方,并且应该在冲击点上获得新的更新位置。

由于碰撞处理程序只是检查他们是否碰撞..我希望是否有办法检测到圆圈碰撞的地方。因此,我可以将碰撞球体的位置更新为最后已知的非碰撞位置,以便它们不能相互穿过并反弹。

+0

由于它们只是圆圈,只需计算圆圈中心点之间的中点即可。如果圆圈有不同的半径,则选择一个圆圈并计算沿距离其中心一个半径的线条的点。 – 2013-03-08 23:15:06

+1

@Chris:比Chris更简单;见下文。 – 2013-03-08 23:15:52

+1

@PieterGeerkens我建议一种简单的方法来计算实际的碰撞位置,从而计算出最接近的非碰撞位置,同时(可能)保持彼此的相对方向/角度,而不仅仅是他们是否碰撞。我认为这就是杰西所要求的。 – 2013-03-08 23:21:05

回答

0

你需要做的是找到两个圆之间的交点,可以是两点,一点或没有。这基本上是通过一起求解两个圆的方程来完成的。这里的数学:

http://www.analyzemath.com/CircleEq/circle_intersection.html

,因为这是学校的,我会离开的编码,到你:)

+0

感谢您的帮助。编码不是问题。无法想出这样做的公式。认为我现在可以开始编码了,谢谢! – 2013-03-08 23:45:29

2

圆的圆周上的所有点与圆心的距离相同。对于比赛场地上的每个圈子都是如此。

因此:当两个圆心之间的距离为< =它们相对半径的总和时,两个圆相互碰撞。

+0

听起来Jesse已经在他们碰撞时正在接电话,但是询问_where_发生了碰撞。 – 2013-03-08 23:16:45

+0

克里斯在说什么。碰撞检测不是问题。它会发现圆环在2D环境中的相交位置,以获取X&Y位置,以将它们放回到尚未与其碰撞的位置。所以他们在圈子的每一边停止移动。 – 2013-03-08 23:44:39

0

好,我们已经标出一个答案,但我去了,把一个全功能的一块的代码,所以也许你可以使用它。 :)从我的评论:

因为他们只是圆圈,只需计算 圈子的中心点之间的中点。如果圆圈有不同的半径,则选择一个圆圈 ,并计算其中心距离 一个半径的线上的点。

这可能是一个简单的实现。我为它创建了一些非常微薄的辅助类;我完全鼓励扩展它们,使结构真正一成不变,以及所有那些优秀的爵士乐,但现在可以用于演示目的。

因此,对于辅助类:

public struct Point 
{ 
    public double X; 
    public double Y; 

    public double Distance(Point otherPoint) 
    { 
     double deltaX = this.X - otherPoint.X; 
     double deltaY = this.Y - otherPoint.Y; 
     return System.Math.Sqrt(deltaX * deltaX + deltaY * deltaY); 
    } 

    public override string ToString() 
    { 
     return String.Format("({0}, {1})", X, Y); 
    } 
} 

public struct Polar 
{ 
    public double Radius; 
    public double Angle; 

    public double X { get { return Radius * System.Math.Cos(Angle); } } 
    public double Y { get { return Radius * System.Math.Sin(Angle); } } 

    public Point ToCartesian() 
    { 
     return new Point() { X = X, Y = Y }; 
    } 
} 

public class Circle 
{ 
    public double Radius { get; set; } 
    public Point Position { get; set; } 
} 

我们的肉和土豆类/方法是这样的:

public class CollisionResult 
{ 
    public Circle Circle1 { get; private set; } 
    public Circle Circle2 { get; private set; } 

    public Point Circle1SafeLocation { get; private set; } 
    public Point Circle2SafeLocation { get; private set; } 

    public Point CollisionLocation { get; private set; } 

    public CollisionResult(Circle circle1, Circle circle2) 
    { 
     this.Circle1 = circle1; 
     this.Circle2 = circle2; 
    } 

    public bool CalculateCollision() 
    { 
     double distanceFromCentres = Circle1.Position.Distance(Circle2.Position); 
     if (distanceFromCentres >= Circle1.Radius + Circle2.Radius) 
      return false; 

     double angleBetweenCircles = System.Math.Atan2(Circle2.Position.Y - Circle1.Position.Y, Circle2.Position.X - Circle1.Position.X); 

     Point midpointBetweenCircles = new Point(){X = (Circle1.Position.X + Circle2.Position.X)/2, Y = (Circle1.Position.Y + Circle2.Position.Y)/2}; 

     Point circle1Offset = (new Polar() { Radius = Circle1.Radius, Angle = System.Math.PI + angleBetweenCircles }).ToCartesian(); 
     Point circle2Offset = (new Polar() { Radius = Circle2.Radius, Angle = angleBetweenCircles }).ToCartesian(); 

     CollisionLocation = midpointBetweenCircles; 
     Circle1SafeLocation = new Point(){X = midpointBetweenCircles.X + circle1Offset.X, Y = midpointBetweenCircles.Y + circle1Offset.Y }; 
     Circle2SafeLocation = new Point(){X = midpointBetweenCircles.X + circle2Offset.X, Y = midpointBetweenCircles.Y + circle2Offset.Y }; 

     return true; 
    } 
} 

使用可能看起来像:

private void CheckCollision(Circle circle1, Circle circle2) 
{ 
    CollisionResult result = new CollisionResult(circle1, circle2); 
    if (result.CalculateCollision()) 
    { 
     Console.WriteLine(String.Format("Collision detected at {0}! Safe location for circle 1: {1}, circle 2: {2}", result.CollisionLocation, result.Circle1SafeLocation, result.Circle2SafeLocation)); 
    } 
    else 
    { 
     Console.WriteLine("Did not collide."); 
    } 
} 

var circle1 = new Circle() {Radius = 5, Position = new Point(){X = 0, Y = 0} }; 
var circle2 = new Circle() {Radius = 5, Position = new Point(){X = 10, Y = 0} }; 
var circle3 = new Circle() {Radius = 3, Position = new Point(){X = 0, Y = 1} }; 
var circle4 = new Circle() {Radius = 5, Position = new Point(){X = 3, Y = 7} }; 

CheckCollision(circle1, circle2); 
CheckCollision(circle3, circle4); 

输出:

Did not collide. 
Collision detected at (1.5, 4)! Safe location for circle 1: (0.158359213500125, 1.31671842700025), circle 2: (3.73606797749979, 8.47213595499958) 

我不知道在你的情况下是否有必要处理计算两个圆的真实交点的复杂性(它们将在两点相交)等等。有可能沿着这些线路就足够了。我绝对鼓励健康的单元测试,并让我的课程超出我在这里的范围适当的。:)

编辑:值得注意的是在这种情况下,这将取决于你想用它来做为你的应用是什么,是当圆重叠,它只是计算它们之间的中点然后移动每圈从该中点离开各自的半径。因此,根据圈子的速度和大小,或者他们如何移动,可能会产生奇怪的结果。例如,如果你有一个半径为10的大圆圈坐着,那么你就会在距离大圆圈中心只有0.5的距离处放置一个半径为1的圆圈,那么这个大圆圈将会移动大约9.75个单位!如果你没有进入重叠的条件,那么这可能不是什么大问题。我认为至少这会给你一些信息关于碰撞,然后如何你想你的圈子作出反应,结果将取决于你。