Change Ball's Color After Collision

Hello! I’m trying to make a simulation about hard-sphere collision with some modifications and I’ve been stuck for days.
This is the output :

However, I want the blue ball to turn its color to red after collided with a red ball. My codes are below.

  1. Main script
Ball[] balls;
int numBalls = 500 ;


void setup() {
  size(500, 500);
  balls = new Ball[numBalls];
  for (int i = 0; i < numBalls; i++) {
    balls[i] = new Ball(random(width), random(height));
  }
}

void draw() {
  background(255);
  for (int i = 0; i < balls.length/3; i++) {
    balls[i].display(255, 0, 0);
    balls[i].move();
  }

  for (int j = balls.length/3 + 1; j < 2*balls.length/3; j++) {
    balls[j].display(0, 255, 0);
    balls[j].move();
  }
  for (int k = (2*balls.length/3) + 1; k < balls.length; k++) {
    balls[k].display(0, 0, 255);
    balls[k].move();
  }
  textSize(40);
  textMode(LEFT);
  fill(0);
  text("", width/4+100, 200);

   for(int i = 0; i < balls.length-1; i++){
   for(int j = i+1; j<balls.length; j++){
   collision(balls[i], balls[j]);
   }
   }
   
   }
   void collision(Ball b1, Ball b2){
   // This solution fixes the glitch that occurs
   // with multiple ball collisions.
   
   float dx = b2.x - b1.x;
   float dy = b2.y - b1.y;
   float dist = sqrt(dx*dx+dy*dy);
   
   if(dist < b1.radius + b2.radius){
   float angle = atan2(dy,dx);
   float sin = sin(angle), cos = cos(angle);
   
   float x1 = 0, y1 = 0;
   float x2 = dx*cos+dy*sin;
   float y2 = dy*cos-dx*sin;
   
   // rotate velocity
   float vx1 = b1.vx*cos+b1.vy*sin;
   float vy1 = b1.vy*cos-b1.vx*sin;
   float vx2 = b2.vx*cos+b2.vy*sin;
   float vy2 = b2.vy*cos-b2.vx*sin;
   
   // resolve the 1D case
   float vx1final = ((b1.mass-b2.mass)*vx1+2*b2.mass*vx2)/(b1.mass+b2.mass);
   float vx2final = ((b2.mass-b1.mass)*vx2+2*b1.mass*vx1)/(b1.mass+b2.mass);
   
   vx1 = vx1final;
   vx2 = vx2final;
   
   // fix the glitch by moving ball part equal to the overlap
   // see video for more details(https://youtu.be/guWIF87CmBg)
   
   float absV = abs(vx1)+abs(vx2);
   float overlap = (b1.radius+b2.radius)-abs(x1-x2);
   x1 += vx1/absV*overlap;
   x2 += vx2/absV*overlap;
   
   // rotate the relative positions back
   float x1final = x1*cos-y1*sin;
   float y1final = y1*cos+x1*sin;
   float x2final = x2*cos-y2*sin;
   float y2final = y2*cos+x2*sin;
   
   
   // finally compute the new absolute positions
   b2.x = b1.x + x2final;
   b2.y = b1.y + y2final;
   
   b1.x = b1.x + x1final;
   b1.y = b1.y + y1final;
   
   //rotate vel back
   b1.vx = vx1*cos-vy1*sin;
   b1.vy = vy1*cos+vx1*sin;
   b2.vx = vx2*cos-vy2*sin;
   b2.vy = vy2*cos+vx2*sin;
   
   
   }
   
} 
  1. Ball object
class Ball {
  float x, y, radius;
  float vx, vy, mass;
  Ball(float x_, float y_) {
    x = x_;
    y = y_;
    radius = random(5, 5);
    vy = random(-1, 1);
    vx = random(-1, 1);
    mass = radius/50;
  }  
  void display(float colora,float colorb, float colorc) {
    fill(colora, colorb, colorc);  
    ellipse(x, y, 2*radius, 2*radius);
  }
  void move() {
    x += vx;
    y += vy;
    if (x > width - radius) {
      x = width - radius;
      vx = -vx;
    }
    if (x < radius) {
      x = radius;
      vx = -vx;
    }
    if (y > height - radius) {
      y = height - radius;
      vy = -vy;
    }
    if (y < radius) {
      y = radius;
      vy = -vy;
    }
  }
}
1 Like

I would choose to store a color inside the Ball class itself. Then, when you initialize the class, you could have the constructor be:

color c;
...
  Ball(float x_, float y_, color c_) {
    x = x_;
    y = y_;
    radius = random(5, 5);
    vy = random(-1, 1);
    vx = random(-1, 1);
    mass = radius/50;
    c = c_;
  }

and your display method would just be

  void display() {
    fill(c);  
    ellipse(x, y, 2*radius, 2*radius);
  }

this cleans up a lot of stuff, since now in your setup method:

  for (int i = 0; i < numBalls; i++) {
    color temp;
    switch (i % 3) {
       case 0:
          temp = color(255, 0, 0);
          break;
       ...
    }
    balls[i] = new Ball(random(width), random(height), temp);
  }

with this approach now, you can implement wherever your balls collide something like:

if (ball 1 is red)
   make ball 2's color red
else if (ball 2 is red)
  make ball 1's color red
3 Likes

Thank you for the reply, I will try to apply your suggestion.