圆形碰撞反应,同时向一个点移动

时间:2012-01-08 00:18:19

标签: java math collision-detection trigonometry geometry

enter image description here

我有圆圈(可能有两个以上)朝着一个点移动。截至目前,它们在接近时会重叠。我怎样才能使它们不相交,但仍然朝着这个方向前进?

我正在使用Java。

  • 圆圈不是遵循物理定律的球,它们 代表有机体(无关)。
  • 我已经进行了碰撞检测
  • 圆圈不会粘在一起,它们根本无法相交。

4 个答案:

答案 0 :(得分:1)

这不是一个简单的问题。

我认为你有一些系统可以计算圆圈的坐标,渲染它们并重复。这些重复称为帧。

每个圆圈都有一个向量,用于描述它应该移动的方向。在每个帧上,您需要执行碰撞检测,并在必要时更改该向量。

任何两个圆之间的碰撞都可以通过检查它们之间的距离是否小于它们的半径之和来检测。碰撞圆的中心之间的线为您提供碰撞的方向。圆的碰撞向量在碰撞方向上,指向圆的中心,其大小等于圆重叠的单位数的一半,即它们的半径之和减去它们之间的距离除以2。 (如果圆圈的大小不等,则变得更加复杂,你需要弄清楚要分割多少。)

因此,解决问题的一种可能方法是简单地将碰撞向量添加到圆的方向向量,然后缩放方向向量,使其大小等于碰撞前的大小。 (这样只调整它的方向,而不是它的大小。)

请注意,这仅适用于您提供的具体描述,您希望球粘在一起并继续朝向该点移动;如果你想要一个更逼真的效果,你需要模仿台球类物理。

答案 1 :(得分:0)

考虑使用现有的2D物理引擎,而不是重新发明轮子。它将为您完成所有碰撞检测,它会很快并且可能会免费为您提供许多很酷的功能。

JBox2D是流行的开源2D物理引擎Box2D的Java端口。一个好的开始。

答案 2 :(得分:0)

我用JQuery做到了。 这是背后的数学 - 没有三角函数。

用一个球朝你想要的方向迈出一小步。

       function pushball(distance,x,y,xgoal,ygoal,step){/
                var factor=1-step/distance;
                var x=xgoal+(xgoal-x)*factor;
                var y=ygoal+(ygoal-y)*factor;
                return [x,y];

检查所有其他球[i]是否发生碰撞。

        function distance(x1,y1,x2,y2){
                 var x=x1-x2;var y=y1-y2;
                 return Math.sqrt(x*x+y*y);
                 }
        var dist=distance(x,y,x[i],y[i]);
        var touch=r+r[i];

现在 - 穿过两个中心点的直线 - 推动其他球(如果它们发生碰撞),这样它们就会相互接触。

        if(dist<touch){
          var range=dist-touch;
          newposxy=pushball(distance,x,y,x[i],y[i],range);
          }

滑动位置发生变化的每个球[i]。意识到x,y是中间点的坐标,而不是左上角的坐标。            $( “#球”)的偏移量({ “左”:Math.round(X [I] -r), “顶部”:Math.round(值Y [i] -1)});

如果您希望看到它有效,请参阅here

答案 3 :(得分:0)

OP解决方案。

感谢:https://web.archive.org/web/20120714122645/http://awesty.com/blog/2008/09/circle-collisions/

public void circleCollision(circle1, circle2) {    
    double xDistance = circle1.x – circle2.x;
    double yDistance = circle1.y – circle2.y;
    double distance = xDistance * xDistance + yDistance * yDistance;
    double angle = Math.atan2(ydist, xdist);

    if (distance < circle1.diameter * circle1.diameter) {
        circle2.x = circle1.x + (circle1.width * Math.cos(angle));
        circle2.y = circle1.y + (circle1.width * Math.sin(angle));
    }
}