简体   繁体   English

向一点移动时发生圈出碰撞反应

[英]Circle collision reaction whilst moving towards a point

在此处输入图片说明

I have circles (there can be more than two) that are moving towards a point. 我有一个圆圈(可以有两个以上)正在接近一个点。 As of now, they overlap when they are close. 截至目前,它们在关闭时重叠。 How can I make it so they do not intersect, but still move towards the point? 我如何才能使它们不相交,但仍朝着重点发展?

I am using Java. 我正在使用Java。

  • The circles are not balls that follow the laws of physics, they represent organisms (irrelevant). 圆圈不是遵循物理定律的球,它们代表有机体(无关紧要)。
  • I already have collision detection working 我已经有碰撞检测功能
  • The circles do not stick together, they simply cannot intersect. 圆圈不粘在一起,根本无法相交。

That's not an easy question. 这不是一个容易的问题。

I presume you have some system which computes the coordinates of the circles, renders them, and repeats. 我假设您有一些系统可以计算圆的坐标,渲染圆并重复。 These repetitions are called frames. 这些重复称为帧。

Each circle has a vector which describes the direction in which it is supposed to move. 每个圆都有一个向量,描述了圆的运动方向。 On each frame you need to perform collision detection, and change that vector if necessary. 在每个帧上,您都需要执行碰撞检测,并在必要时更改该矢量。

Collision between any two circles can be detected by checking to see whether the distance between them is smaller than the sum of their radii. 可以通过检查两个圆之间的距离是否小于其半径之和来检测任意两个圆之间的碰撞。 The line between the centers of the colliding circles gives you the direction of the collision. 碰撞圆心之间的线为您提供碰撞的方向。 The collision vector for a circle is on the direction of the collision, pointing towards the center of the circle, and its magnitude is equal to half the number of units by which the circles overlap, that is, to the sum of their radii minus the distance between them, divided by two. 圆的碰撞矢量在碰撞的方向上,指向圆的中心,其大小等于圆重叠的单位数的一半,即等于圆的半径减去它们之间的距离除以二。 (If the circles can be of unequal sizes it becomes more complicated, you need to figure out by how much to divide.) (如果圆的大小可能不相等,则它会变得更加复杂,您需要找出要除以多少。)

So, one possible solution to your problem would be to simply add the collision vector to the direction vector of the circle and then scale the direction vector so that its magnitude is equal to the magnitude that it had before the collision. 因此,解决您的问题的一种可能的方法是,将碰撞矢量简单地添加到圆的方向矢量上,然后缩放方向矢量,以使其大小等于碰撞前的大小。 (So that only its direction will be adjusted, not its magnitude.) (因此仅调整其方向,而不调整其大小。)

Note that this will only work for the specific description that you gave, where you want the balls to stick together and continue moving towards the point; 请注意,这仅适用于您给出的特定描述,即您希望球粘在一起并继续朝着该点移动; if you wanted a more realistic effect, you would need to emulate billiard balls type of physics. 如果您想获得更逼真的效果,则需要模拟台球物理类型。

I did it with JQuery. 我用JQuery做到了。 Here is the math behind - without trigonometric functions. 这是背后的数学原理-没有三角函数。

Make a small step with one Ball to the direction you want it to go. 用一个球朝您想要的方向走一小步。

       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];

Check all other balls[i] whether they collide. 检查所有其他球[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];

Now - on a straight line through the two center point - push the other balls (if they collide) so that they just touch each other. 现在-在穿过两个中心点的直线上-推动其他球(如果它们发生碰撞),使其彼此接触。

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

Slide each ball[i] whose position has changed. 滑动位置已更改的每个球[i]。 Aware that x,y are the coordinates of the middle point and not of the top left corner. 注意x,y是中间点的坐标,而不是左上角的坐标。 $("#ball").offset({"left":Math.round(x[i]-r),"top":Math.round(y[i]-r)}); $( “#球”)的偏移量({ “左”:Math.round(X [I] -r), “顶部”:Math.round(值Y [i] -1)});

If you want to see it working see here 如果您想看到它正常工作,请点击这里

Solution by OP. 由OP解决。

Thanks to: https://web.archive.org/web/20120714122645/http://awesty.com/blog/2008/09/circle-collisions/ 感谢: 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));
    }
}

Rather than reinvent the wheel, consider using an existing 2D physics engine. 与其重新发明轮子,不如考虑使用现有的2D物理引擎。 It will do all the collision detection for you, it will be fast and will probably provide you with a lot of cool functionality for free. 它会为您完成所有的碰撞检测,而且速度很快,并且可能会免费为您提供许多出色的功能。

JBox2D is a Java port of the popular open source 2D physics engine Box2D . JBox2D是流行的开源2D物理引擎Box2D的Java端口。 A good place to start. 一个很好的起点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM