Using dist(); for collision detection

Hello processing community. I want to make a mini game where you control a ellipse and have to avoid other ellipse. I first wanted the “opponents” to repel each other. For this I initialized 10 ellipses in an array. But when I try to use the dist function to see if the radius overlaps, it only shows that the dist function doesn’t expect a float parameters. Are there other solutions or can you convert your array in some way so that it is still possible to use dist.

int ballCount = 10;
float r = 60;
float angle=10;
float[] x = new float[ballCount];
float[] y = new float[ballCount];
float[] xSpeed = new float[ballCount];
float[] ySpeed = new float[ballCount];

void gegner(){
  for(int j = 0; j < ballCount; j++){

    x[j] += xSpeed[j];
    if(x[j] < 133 || x[j] > width-130){
      xSpeed[j] *= -1;
    }

    y[j] += ySpeed[j];
    if(y[j] < 133 || y[j] > height-130){
      ySpeed[j] *= -1;
    } 
    
    
    if(dist(x=xSpeed, y=xSpeed, x[j], y[j]) < r)

{
   if(xSpeed >0){
     xSpeed = -1;
    }
   else if(xSpeed < 0){
      xSpeed = 1;
    }
    if(ySpeed > 0){
      ySpeed = -1;
    }
    else if(ySpeed < 0){
      ySpeed = 1;
    }
    
 }
  
  stroke(0);
fill(0);
    ellipse(x[j], y[j],r,r);
    fill(#2BFF03);
    rect(x[j], y[j],20,20);  
}}




void setup(){
size (800,800);
for(int j = 0; j < ballCount; j++){
    x[j] = random(200,800);
    y[j] = random(200,800);
    xSpeed[j] = random(2.5, 3);
    ySpeed[j] = random(2.5, 3);}
}


void draw() {
  background(0);

gegner();

}

The problem with your code is that you are trying to pass in an array as a parameter to the “dist()” function, but the “dist()” function expects individual x and y coordinates as parameters. To fix this issue, you can simply use the values from the x and y arrays in the “dist()” function instead of passing in the entire array.

For example, to calculate the distance between the first and second ellipse in your array, you can use the following code:

if(dist(x[0], y[0], x[1], y[1]) < r)

You can then use a loop to check the distance between each ellipse in the array and apply the necessary changes to the x and y speeds if the distance is less than the radius.

Note: part of this message was generated with ChatGPT

Thanks, I’m a lot closer now. The problem that now exists is that if, for example, I let the 2 ellipse bounce off the rest, it is completely frozen. But the others are completely normal and bounce off the 2 ellipse. But if I now want to let all of them bounce, of one another if(dist(x[j], y[j], x[j], y[j]) < r), the problem with the freeze applys onto all ellipses.

int ballCount = 10;
float r = 60;
float angle=10;
float[] x = new float[ballCount];
float[] y = new float[ballCount];
float[] xSpeed = new float[ballCount];
float[] ySpeed = new float[ballCount];

void gegner(){
  for(int j = 0; j < ballCount; j++){

    x[j] += xSpeed[j];
    if(x[j] < 133 || x[j] > width-130){
      xSpeed[j] *= -1;
    }

    y[j] += ySpeed[j];
    if(y[j] < 133 || y[j] > height-130){
      ySpeed[j] *= -1;
    }   if(dist(x[1], y[1], x[j], y[j]) < r){
    xSpeed[j] *= -1;
    ySpeed[j] *= -1;
    }
  stroke(0);
fill(0);
    ellipse(x[j], y[j],r,r);
    fill(#2BFF03);
    rect(x[j]-10, y[j]-10,20,20);  
} }

void setup(){
size (800,800);
for(int j = 0; j < ballCount; j++){
    x[j] = random(200,600);
    y[j] = random(200,600);
    xSpeed[j] = random(2.5, 3);
    ySpeed[j] = random(2.5, 3);}
}


void draw() {
  background(255);

gegner();

}

The issue is that your code is only checking for a collision between the first second ball and the other balls:

if(dist(x[1], y[1], x[j], y[j]) < r)

You need to add a nested loop to check for collisions between all of the balls.

Here is an example of how you can do this:

for(int i = 0; i < ballCount; i++){
  for(int j = 0; j < ballCount; j++){
    if(i != j && dist(x[i], y[i], x[j], y[j]) < r){
      xSpeed[i] *= -1;
      ySpeed[i] *= -1;
      xSpeed[j] *= -1;
      ySpeed[j] *= -1;
    }
  }
}

This code checks for a collision between each pair of balls and reverses their speed if they are colliding. It also ensures that a ball does not collide with itself by checking if i and j are the same. You can add this code inside your gegner() function.

A more object oriented approach would be to create a Ball class with a method that takes an array of Balls and checks for collisions against all of them.

Note: part of this message was generated with ChatGPT

2 Likes

You can make this double loop more efficient with

for(int i = 0; i < ballCount - 1; i++){
  for(int j = i + 1; j < ballCount; j++){
    if(dist(x[i], y[i], x[j], y[j]) < r){
      xSpeed[i] *= -1;
      ySpeed[i] *= -1;
      xSpeed[j] *= -1;
      ySpeed[j] *= -1;
    }
  }
}

It reduces the number of tests by half and avoids having to compare i and j because it is now impossible for them to be equal

2 Likes

I just realised that there is an algorithmic logic error in the double loop code presented by @sableRalph

Consider a system with 4 balls this table identifies the collision tests

+ = collision test
- =  no collision test

          i = 
        0  1  2  3
    0   -  +  +  +    
j   1   +  -  +  +
=   2   +  +  -  +
    3   +  +  +  -

Notice that for any pairs of balls where i != j two tests are performed and the speed will be multiplied by -1 twice, in other words multiplied by 1 so no change of direction

This type of problem is well suited to OO programming but this is not a good idea because
you end up sending the same array to every ball thus having the same problem that I have just described.

Personally I would perform the collision detection outside the ball class (in the main sketch or another class used to manage the application.

3 Likes

Example w/ double loop circle collision detection:
“Linked Balls”