Issue in ellipse collision

CowDemo.pde

ArrayList<Cow> particles;

void setup() {
  frameRate(30);
  //size(1000, 800);
  size(300, 300);
  particles = new ArrayList<Cow>();
  for (int i = 0; i <= 1; i++) {
    particles.add(new Cow());
  }
}

void draw() {
  background(200);

  for (Cow c : particles) {
    c.collide(particles);
    c.move();
    c.display();
  }

  fill(0);
  textSize(20);
  text("FPS: "+frameRate+"Cows: "+particles.size(), 0, 20);
}

void mousePressed() {
  if (mouseButton == RIGHT) {
    particles.add(new Cow(20+(int)(Math.random()*30), mouseX, mouseY, random(6)-3, random(6)-3));
  }

  for (Cow c : particles) {
    c.click();
  }
}

void keyPressed() {
  if (keyCode == 32) {
    particles.clear();
  }
}

Cow.pde

public class Cow {
  float x, y, dx, dy, radius;
  color c;
  boolean colliding = false;
  boolean selected = false;

  Cow(float rad, float x, float y, float dx, float dy) {
    radius = rad;
    this.x = x;
    this.y = y;
    this.dx = (int)(dx*100)/50.0;
    this.dy = (int)(dy*100)/50.0;
    c = color(random(255), random(255), random(255));
  }

  Cow() {
    this(20+(int)(Math.random()*30), width/2, height/2, random(6)-3, random(6)-3);
  }

  void move() {
    int mult = 1;
    if (selected && colliding) {
      mult = 2;
    } 

    x += dx * mult;
    y += dy * mult;

    if (x + radius > width || x - radius < 0) dx *= -1;
    if (y + radius > height || y - radius < 0) dy *= -1;
  }

  void display() {
    noStroke();

    if (colliding) {
      fill(255, 0, 0, 100);
    } else {
      fill(c);
    }

    ellipse(x, y, radius*2, radius*2);

    if (selected) {
      fill(255);
      ellipse(x-10, y, 5, 5);
      ellipse(x+10, y, 5, 5);
      fill(0);
      text("Dx: "+this.dx+"\nDy: "+this.dy, 0, 50);
    }
  }

  void click() {
    if (dist(mouseX, mouseY, this.x, this.y) <= radius) {
      selected = !selected;
    } else {
      selected = false;
    }
  }

  void collide(ArrayList<Cow> others) {
    for (Cow oc : others) {
      if (oc != this && dist(oc.x, oc.y, this.x, this.y) <= (oc.radius + this.radius)) {
        this.colliding = true;
      } else {
        this.colliding = false;
      }
    }
  }
}

In the cow, class collides method I wrote the method to check the distance between other ellipses and if they collide to true the collision variable in the current object. so that it should also be another object in the next iteration so that both objects should get collision true right? but for some strange issue it’s not happening. only one ellipse in collision gets that collision variable true.

Any help would be highly appreciated.

Try adding oc.colliding = true; in your collide code.

1 Like

that is not working either.

you need to test the collision on all cows.

ie

void collide(ArrayList<Cow> others) {
    int k = 0;
    for (Cow oc : others) {
      if (oc != this && dist(oc.x, oc.y, this.x, this.y) <= (oc.radius + this.radius)) {
        k ++;
      }
    }
    if(k>0)colliding = true;
    else colliding = false;
  }
1 Like

Thanks, man, this worked. Really appreciate the support, you saved my day! I’m still thinking why the previous code wasn’t working :zipper_mouth_face: but now I have a reference so I’ll figure it out eventually. :wink:

essentially your test would fail for the following reason.

if you are looping through the array and setting colliding on for each of them then the program logic would be as follows

index 1
test
collided
therefore set collide to true

index 2
test
not collided
therefore set collide to false
// collided is now false although it should be true;
index 3
test
not collided
therefore set collide to false

so in the end the test fails despite the fact that there is a collision in index one. Hence you can use a counter instead. Each time the counter is greater than 0 you can be sure there is a collision as you are never reseting the counter inside the loop.

to improve performance you can also add a break clause.

void collide(ArrayList<Cow> others) {
    int k = 0;
    for (Cow oc : others) {
      if (oc != this && dist(oc.x, oc.y, this.x, this.y) <= (oc.radius + this.radius)) {
        k ++;
        break;
      }
    }
    if(k>0)colliding = true;
    else colliding = false;
  }
1 Like

Wow nice, got it. 100% clear now. Thank you very much! :star_struck:

1 Like