2
votes

enter image description here

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.

  • 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.
4
I think you need to go into further detail as to what the behaviour should be when the circles collide.Mark Peters
Do you want to know how to do this from scratch yourself or would you like to know libraries in Java that can help with this?Tim Gee
Those circles in your image are going to collide at some point.Perception
Please post your solution in its own answer, not as an edit.Cœur

4 Answers

1
votes

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.

0
votes

Rather than reinvent the wheel, consider using an existing 2D physics engine. 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. A good place to start.

0
votes

I did it with 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.

        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. Aware that x,y are the coordinates of the middle point and not of the top left corner. $("#ball").offset({"left":Math.round(x[i]-r),"top":Math.round(y[i]-r)});

If you want to see it working see here

0
votes

Solution by OP.

Thanks to: 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));
    }
}