Trigger animation effect after object collision

I want to create a “pulse” effect after objects collide with each other. The intended effect in this example is that when the particles collide (come within a certain distance from each other) an ellipse appears, grows to a specified radius, then disappears. The ellipse x, y coordinates will be the same as the particle’s (ellipse moves with the particle). And this animation should occur as a trigger - once triggered, the distance between particles should no longer matter.

In the code below the effect is not what I’m intending. Instead of the particle continuing it’s trajectory at the same velocity with an ellipse growing from the center, the particle slows down, an ellipse appears for the time that the two particles are near each other, then disappears.

Here’s a sample:

ArrayList<Particle> particles;

void setup() {
  size(400, 400);
  particles = new ArrayList<Particle>();
  int numparticles = 2;
  for (int i=0; i < numparticles; i++) {
    float initX = random(0, width);
    float initY = random(0, height);
    Particle particle = new Particle(initX, initY);
    particles.add(particle);
  }
}

void draw() {
  background(0);
  // There's a much cleaner way to do this, but showing this
  // way to illustrate the example.
  Particle particle1 = particles.get(0);
  Particle particle2 = particles.get(1);
  
  // Make the particles seek each other
  particle1.seek(particle2.pos);
  particle2.seek(particle1.pos);
  
  // Update position and display
  particle1.update();
  particle1.display();
  
  particle2.update();
  particle2.display();
  
  // NEED HELP: Attempt at interaction here.
  for (Particle particle : particles) {
    particle.interact(particles,25); 
  }
}

class Particle {
  PVector pos;
  PVector velocity;
  PVector acceleration;
  float maxforce;
  float maxspeed;
  float r;
  boolean interacting;
  
  Particle(float x, float y) {
    acceleration = new PVector(0, 0);
    velocity = new PVector(0, 0);
    pos = new PVector(x, y);
    maxspeed = 4.0;
    maxforce = 0.03;
    r = 15;
    interacting = false;
  }
  
  void applyForce(PVector force) {
    acceleration.add(force); 
  }
  
  void seek(PVector target) {
    PVector desired = PVector.sub(target, pos);
    desired.normalize();
    desired.mult(maxspeed);
    PVector steer = PVector.sub(desired, velocity);
    steer.limit(maxforce);
    applyForce(steer);
  }
  
  // NEED HELP HERE:
  // if the particles come within a certain distance
  // then interact by pulsing a circle.
  // The pulse effect should be a circle that grows until
  // it reaches a set radius, then disappears.
  // The pulsing circle will be centered at the particle's
  // x,y coordinates at each step.
  void interact(ArrayList<Particle> particles, float radius) {
    for (Particle other : particles) {
      float iradius = 0.0;
      float d = PVector.dist(pos, other.pos);
      
      // trigger the interaction.
      if ((d > 0) && (d <= radius)) {
        interacting = true;
      }
      
      // NEED HELP HERE.
      // what to do while interacting.
      while (interacting) {
        if (iradius < radius) {
          pushMatrix();
            noFill();
            stroke(255, 255, 0);
            ellipse(pos.x, pos.y, iradius, iradius);
          popMatrix();
          iradius += 0.01;           
        } else {
          interacting = false;
        }
      }
    }
   } // end interact function.
  
  void update() {
    velocity.add(acceleration);
    velocity.limit(maxspeed);
    pos.add(velocity);
    acceleration.mult(0);
  }
  
  void display() {
    fill(255);
    ellipse(pos.x, pos.y, r, r);
  }
  
} // end Particle```
1 Like

Hello !

and welcome to this forum! It’s a great community.

Wow, you posted a very good code and formatted correctly… you are way ahead already…

One remark:

The way you do it, you compare all particles to all particles (one for loop in draw calling another one in interact()). This is technically too often. Instead you could have :

for loop i1 0 to size-1
    for loop i2+1 to size

thus you avoid

  • comparing a to b and later b to a.
  • comparing also a to a

Your question :

It’s good that you have the variable interacting and that it stays true once it is true. Because then the pulse can go on even when the particle has moved on (and the distance is bigger again).

but you have a while loop doing the pulse and that’s wrong, because the screen gets updated only once at the end of draw() and not throughout. (or do you want to draw multiple rings at once?)

so have this

if(interacting) {
        if (iradius < radius) {
          pushMatrix();
            noFill();
            stroke(255, 255, 0);
            ellipse(pos.x, pos.y, iradius, iradius);
          popMatrix();
          iradius += 0.01;           
        } else {
          interacting = false;
        }
}

but inside of the method display() in the class!

Also you want to store the position of the ellipse in the moment of the collision in an extra variable and display the pulse there, because the ellipses would move on but the pulse should not.

pushMatrix and popMatrix is not necessary with

        ellipse(x1, y1, 
          iradius, iradius);

It’s only necessary if you’d use translate etc.

Chrisir

My version



ArrayList<Particle> particles;

void setup() {
  size(400, 400);
  particles = new ArrayList<Particle>();
  int numparticles = 2;
  for (int i=0; i < numparticles; i++) {
    float initX = random(0, width);
    float initY = random(0, height);
    Particle particle = new Particle(initX, initY, i);
    particles.add(particle);
  }
}

void draw() {
  background(0);

  // There's a much cleaner way to do this, but showing this
  // way to illustrate the example.
  Particle particle1 = particles.get(0);
  Particle particle2 = particles.get(1);

  // Make the particles seek each other
  particle1.seek(particle2.pos);
  particle2.seek(particle1.pos);

  // Update position and display
  particle1.update();
  particle1.display();

  particle2.update();
  particle2.display();

  // NEED HELP: Attempt at interaction here.
  for (Particle particle : particles) {
    particle.interact(particles, 25);
  }
}

// =================================================================

class Particle {
  PVector pos;
  PVector velocity;
  PVector acceleration;
  float maxforce;
  float maxspeed;
  float r;
  boolean interacting;

  int id;

  float iradius = 0.0;
  float radius = 25.0;
  float x1, y1; 

  //constr
  Particle(float x, float y, 
    int i_) {
    acceleration = new PVector(0, 0);
    velocity = new PVector(0, 0);
    pos = new PVector(x, y);
    maxspeed = 4.0;
    maxforce = 0.03;
    r = 15;
    interacting = false;

    id=i_;
  } //constr

  void applyForce(PVector force) {
    acceleration.add(force);
  }

  void seek(PVector target) {
    PVector desired = PVector.sub(target, pos);
    desired.normalize();
    desired.mult(maxspeed);
    PVector steer = PVector.sub(desired, velocity);
    steer.limit(maxforce);
    applyForce(steer);
  }

  // NEED HELP HERE:
  // if the particles come within a certain distance
  // then interact by pulsing a circle.
  // The pulse effect should be a circle that grows until
  // it reaches a set radius, then disappears.
  // The pulsing circle will be centered at the particle's
  // x,y coordinates at each step.
  void interact(ArrayList<Particle> particles, 
    float radius) {
    for (Particle other : particles) {

      if (id==other.id) {
        return;
      }

      float d = PVector.dist(pos, other.pos);

      // trigger the interaction.
      if ( d <= radius ) {
        interacting = true;
        iradius = 0.0;
        x1=(pos.x+other.pos.x)/2;
        y1=(pos.y+other.pos.y)/2;
        println("hit");
      }
    }
  } // end interact function.

  void update() {
    velocity.add(acceleration);
    velocity.limit(maxspeed);
    pos.add(velocity);
    acceleration.mult(0);
  }

  void display() {
    fill(255);
    ellipse(pos.x, pos.y, r, r);

    if (interacting) {
      if (iradius < radius+20) {
        //pushMatrix();
        noFill();
        // fill(255, 255, 0);
        stroke(255, 255, 0);

        ellipse(x1, y1, 
          iradius, iradius);
        //popMatrix();
        iradius += 1.101;
      } else {
        interacting = false;
      }
    }
  }//func
} // end Particle class
//
1 Like

you can also use a while loop to draw many rings and let it grow

see here


ArrayList<Particle> particles;

void setup() {
  size(400, 400);
  particles = new ArrayList<Particle>();
  int numparticles = 2;
  for (int i=0; i < numparticles; i++) {
    float initX = random(0, width);
    float initY = random(0, height);
    Particle particle = new Particle(initX, initY, i);
    particles.add(particle);
  }
}

void draw() {
  background(0);

  // There's a much cleaner way to do this, but showing this
  // way to illustrate the example.
  Particle particle1 = particles.get(0);
  Particle particle2 = particles.get(1);

  // Make the particles seek each other
  particle1.seek(particle2.pos);
  particle2.seek(particle1.pos);

  // Update position and display
  particle1.update();
  particle1.display();

  particle2.update();
  particle2.display();

  // NEED HELP: Attempt at interaction here.
  for (Particle particle : particles) {
    particle.interact(particles, 25);
  }
}

// =================================================================

class Particle {
  PVector pos;
  PVector velocity;
  PVector acceleration;
  float maxforce;
  float maxspeed;
  float r;
  boolean interacting;

  int id;

  int iradius = 0;
  float radius = 25.0;
  float x1, y1; 

  int max; 

  //constr
  Particle(float x, float y, 
    int i_) {
    acceleration = new PVector(0, 0);
    velocity = new PVector(0, 0);
    pos = new PVector(x, y);
    maxspeed = 4.0;
    maxforce = 0.03;
    r = 15;
    interacting = false;

    id=i_;
  } //constr

  void applyForce(PVector force) {
    acceleration.add(force);
  }

  void seek(PVector target) {
    PVector desired = PVector.sub(target, pos);
    desired.normalize();
    desired.mult(maxspeed);
    PVector steer = PVector.sub(desired, velocity);
    steer.limit(maxforce);
    applyForce(steer);
  }

  // NEED HELP HERE:
  // if the particles come within a certain distance
  // then interact by pulsing a circle.
  // The pulse effect should be a circle that grows until
  // it reaches a set radius, then disappears.
  // The pulsing circle will be centered at the particle's
  // x,y coordinates at each step.
  void interact(ArrayList<Particle> particles, 
    float radius) {
    for (Particle other : particles) {

      // we don't want to compare a against a
      if (id==other.id) {
        return;
      }

      float d = pos.dist(other.pos);

      // trigger the interaction.
      if ( d <= radius ) {
        interacting = true;
        iradius     = 5;
        max         = 17; 
        x1 = (pos.x+other.pos.x)/2;
        y1 = (pos.y+other.pos.y)/2;
        // println("hit");
      }
    }
  } // end interact function.

  void update() {
    velocity.add(acceleration);
    velocity.limit(maxspeed);
    pos.add(velocity);
    acceleration.mult(0);
  }

  void display() {
    fill(255);
    ellipse(pos.x, pos.y, r, r);

    if (interacting) {
      iradius=0;
      while (iradius < max) {
        noFill();
        stroke(255, 255, 0);
        ellipse(x1, y1, 
          iradius, iradius);
        iradius += 9;
      }
      max += 1.101;
      if (max > 86) {
        interacting = false;
      }
    }
  }//func
} // end Particle class
//
1 Like

@Chrisir Thank you. You clarified for me how to get the triggered effect - putting that in display() instead of the interact function itself. Now, with the code below I’m expecting each particle to display the effect. However, only one does when the particles cross paths.

I would expect that in for each loop of draw() this piece of code would run for each particle, and trigger the interaction effect

// NEED HELP: Attempt at interaction here.
  for (Particle particle : particles) {
    particle.interact(particles,25); 
  }

But instead, the effect only triggers for a single particle. Any idea for why?

ArrayList<Particle> particles;

void setup() {
  size(400, 400);
  particles = new ArrayList<Particle>();
  int numparticles = 2;
  for (int i=0; i < numparticles; i++) {
    float initX = random(0, width);
    float initY = random(0, height);
    Particle particle = new Particle(initX, initY, i);
    particles.add(particle);
  }
}

void draw() {
  background(0);
  // There's a much cleaner way to do this, but showing this
  // way to illustrate the example.
  Particle particle1 = particles.get(0);
  Particle particle2 = particles.get(1);
  
  // Make the particles seek each other
  particle1.seek(particle2.pos);
  particle2.seek(particle1.pos);
  
  // Update position and display
  particle1.update();
  particle1.display();
  
  particle2.update();
  particle2.display();
  
  // NEED HELP: Attempt at interaction here.
  for (Particle particle : particles) {
    particle.interact(particles,25); 
  }
  
  
  
}

class Particle {
  PVector pos;
  PVector velocity;
  PVector acceleration;
  float maxforce;
  float maxspeed;
  float r;
  boolean interacting;
  
  int id;
  
  float iradius = 0.0;
  float radius = 50.0;
  float x1, y1;
  
  Particle(float x, float y, int id_) {
    acceleration = new PVector(0, 0);
    velocity = new PVector(0, 0);
    pos = new PVector(x, y);
    maxspeed = 4.0;
    maxforce = 0.03;
    r = 15;
    interacting = false;
    id = id_;
  }  // end Particle constructor
  
  void applyForce(PVector force) {
    acceleration.add(force); 
  }
  
  void seek(PVector target) {
    PVector desired = PVector.sub(target, pos);
    desired.normalize();
    desired.mult(maxspeed);
    PVector steer = PVector.sub(desired, velocity);
    steer.limit(maxforce);
    applyForce(steer);
  }
  
  // NEED HELP HERE:
  // if the particles come within a certain distance
  // then interact by pulsing a circle.
  // The pulse effect should be a circle that grows until
  // it reaches a set radius, then disappears.
  // The pulsing circle will be centered at the particle's
  // x,y coordinates at each step.
  void interact(ArrayList<Particle> particles, float radius) {
    for (Particle other : particles) {
      if (id == other.id) {
        return; 
      }
      float d = PVector.dist(pos, other.pos);
      
      // trigger the interaction.
      if (d <= radius) {
        interacting = true;
        iradius = 0.0;
        x1 = (pos.x + other.pos.x)/2;
        y1 = (pos.y + other.pos.y)/2;
      }
    }
   } // end interact function.
  
  void update() {
    velocity.add(acceleration);
    velocity.limit(maxspeed);
    pos.add(velocity);
    acceleration.mult(0);
  }
  
  void display() {
    fill(255);
    ellipse(pos.x, pos.y, r, r);
    
    if (interacting) {
      if (iradius < radius) {
        noFill();
        stroke(255, 255, 0);
        ellipse(pos.x, pos.y, iradius, iradius);
        iradius += 0.7;
      } else {
        interacting = false; 
      }
    }
  } // end display function.
  
} // end Particle class.
1 Like

here

I first had it so that the pulse was in the place where the collision occurred (x1,y1) and stayed there.

Now the pulse goes with both circles.

Chrisir

ArrayList<Particle> particles;

void setup() {
  size(400, 400);

  particles = new ArrayList<Particle>();
  int numparticles = 2;
  for (int i=0; i < numparticles; i++) {
    float initX = random(0, width);
    float initY = random(0, height);
    Particle particle = new Particle(initX, initY, i);
    particles.add(particle);
  }
}

void draw() {
  background(0);

  // There's a much cleaner way to do this, but showing this
  // way to illustrate the example.
  Particle particle1 = particles.get(0);
  Particle particle2 = particles.get(1);

  // Make the particles seek each other
  particle1.seek(particle2.pos);
  particle2.seek(particle1.pos);

  // Update position and display
  particle1.update();
  particle1.display();

  particle2.update();
  particle2.display();

  // NEED HELP: Attempt at interaction here.
  for (Particle particle : particles) {
    particle.interact(particles, 25);
  }
}

// ============================================================

class Particle {
  // 
  PVector pos;
  PVector velocity;
  PVector acceleration;
  float maxforce;
  float maxspeed;
  float r = 15;
  boolean interacting = false;

  int id;

  float iradius = 0.0;
  float radius = 50.0;
  //  float x1, y1;

  Particle(float x, float y, 
    int id_) {
    acceleration = new PVector(0, 0);
    velocity = new PVector(0, 0);
    pos = new PVector(x, y);
    maxspeed = 4.0;
    maxforce = 0.03;

    id = id_;
  }  // end Particle constructor

  void applyForce(PVector force) {
    acceleration.add(force);
  }

  void seek(PVector target) {
    PVector desired = PVector.sub(target, pos);
    desired.normalize();
    desired.mult(maxspeed);
    PVector steer = PVector.sub(desired, velocity);
    steer.limit(maxforce);
    applyForce(steer);
  }

  // NEED HELP HERE:
  // if the particles come within a certain distance
  // then interact by pulsing a circle.
  // The pulse effect should be a circle that grows until
  // it reaches a set radius, then disappears.

  // The pulsing circle will be centered at the particle's
  // x,y coordinates at each step.
  void interact(ArrayList<Particle> particles, float radius) {
    for (Particle other : particles) {
      if (id == other.id) {
        continue; // skip
      }
      float d = PVector.dist(pos, other.pos);

      // trigger the interaction.
      if (d <= radius) {
        interacting = true;
        iradius = r;
        //x1 = (pos.x + other.pos.x)/2;
        //y1 = (pos.y + other.pos.y)/2;
      }
    }
  } // end interact function.

  void update() {
    velocity.add(acceleration);
    velocity.limit(maxspeed);
    pos.add(velocity);
    acceleration.mult(0);
  }

  void display() {
    fill(255);
    ellipse(pos.x, pos.y, 
      r, r);

    if (interacting) {
      if (iradius < radius+22) {
        noFill();
        stroke(255, 255, 0);
        ellipse(pos.x, pos.y, 
          iradius, iradius);
        iradius += 2.07;
      } else {
        interacting = false;
      }
    }
  } // end display function.
  //
} // end Particle class.
//

this was one big error by me.

It must be


if (id == other.id) { 
   continue; 
}

new version with different colors


ArrayList<Particle> particles;

void setup() {
  size(400, 400);

  particles = new ArrayList<Particle>();
  int numparticles = 2;
  for (int i=0; i < numparticles; i++) {
    float initX = random(0, width);
    float initY = random(0, height);
    Particle particle = new Particle(initX, initY, i);
    particles.add(particle);
  }
}

void draw() {
  background(0);

  // There's a much cleaner way to do this, but showing this
  // way to illustrate the example.
  Particle particle1 = particles.get(0);
  Particle particle2 = particles.get(1);

  // Make the particles seek each other
  particle1.seek(particle2.pos);
  particle2.seek(particle1.pos);

  // Update position and display
  particle1.update();
  particle1.display();

  particle2.update();
  particle2.display();

  // NEED HELP: Attempt at interaction here.
  for (Particle particle : particles) {
    particle.interact(particles, 25);
  }
}

// ============================================================

class Particle {
  // 
  PVector pos;
  PVector velocity;
  PVector acceleration;
  float maxforce;
  float maxspeed;
  float r = 15;
  boolean interacting = false;
  float pulseSpeed;

  int id;

  float iradius = 0.0;
  float radius = 50.0;
  color colEllipse = color (random(255), 0, random(255)); 

  Particle(float x, float y, 
    int id_) {
    acceleration = new PVector(0, 0);
    velocity = new PVector(0, 0);
    pos = new PVector(x, y);
    maxspeed = 4.0;
    maxforce = 0.03;

    id = id_;

    // we can make the pulse of #0 of different speed
    if (id==0) 
      pulseSpeed=0.9;
    else pulseSpeed=0.9;
    //
  }  // end Particle constructor

  void applyForce(PVector force) {
    acceleration.add(force);
  }

  void seek(PVector target) {
    PVector desired = PVector.sub(target, pos);
    desired.normalize();
    desired.mult(maxspeed);
    PVector steer = PVector.sub(desired, velocity);
    steer.limit(maxforce);
    applyForce(steer);
  }

  // NEED HELP HERE:
  // if the particles come within a certain distance
  // then interact by pulsing a circle.
  // The pulse effect should be a circle that grows until
  // it reaches a set radius, then disappears.

  // The pulsing circle will be centered at the particle's
  // x,y coordinates at each step.
  void interact(ArrayList<Particle> particles, float radius) {
    for (Particle other : particles) {
      if (id == other.id) {
        continue; // skip
      }
      float d = PVector.dist(pos, other.pos);

      // trigger the interaction.
      if (d <= radius) {
        interacting = true;
        iradius = r+2;
        //x1 = (pos.x + other.pos.x)/2;
        //y1 = (pos.y + other.pos.y)/2;
      }//if
    }//for
  } // end interact function.

  void update() {
    velocity.add(acceleration);
    velocity.limit(maxspeed);
    pos.add(velocity);
    acceleration.mult(0);
  }

  void display() {
    fill(colEllipse);
    noStroke(); 
    ellipse(pos.x, pos.y, 
      r, r);

    if (interacting) {
      if (iradius < radius) {
        noFill();
        stroke(255, 255, 0);
        ellipse(pos.x, pos.y, 
          iradius, iradius);
        iradius += pulseSpeed;
      } else {
        interacting = false;
      }
    }
  } // end display function.
  //
} // end Particle class.
//

Remark I


      if (id == other.id) {
        continue; // skip
      }

OR more comprehensible

  // The pulsing circle will be centered at the particle's
  // x,y coordinates at each step.
  void interact(ArrayList<Particle> particles, float radius) {

    for (Particle other : particles) {

      if (id != other.id) {  // !!!!!!!!!!!!!!!!!!

      float d = PVector.dist(pos, other.pos);

      // trigger the interaction.
      if (d <= radius) {
        interacting = true;
        iradius = r+2;
        //x1 = (pos.x + other.pos.x)/2;
        //y1 = (pos.y + other.pos.y)/2;
      }//if
     }//if
    }//for
  } // end interact function.

Remark II

as I mentioned compare all against all is time consuming (you compare double)

instead in draw

for loop i1 0 to size-1
    for loop i2+1 to size

and then in interact() set both particles interacting = true;

Chrisir

2 Likes

@Chrisir Thanks for the tips. Help me dig in a bit and understand how to implement this. I love to find efficiency where possible.

With the change you outlined would I still need to pass the ArrayList<Particle> object to the Particle.interact() method?

Or would I change this to accept a single instance of Particle (and pass each Particle object from the particles array using a loop in the draw() function like you one you posted?

Here is my implementation of the code suggestions above. Comments, suggestions, tips are welcome.

ArrayList<Particle> particles;

void setup() {
  size(400, 400);

  particles = new ArrayList<Particle>();
  int numparticles = 2;
  for (int i=0; i < numparticles; i++) {
    int initX = int(random(0, width));
    int initY = int(random(0, height));
    Particle particle = new Particle(initX, initY, i);
    particles.add(particle);
  }
}

void draw() {
  background(0);

  for (int i=0; i<particles.size()-1; i++) {
    for (int j=i+1; j<particles.size(); j++) {
      Particle particle = particles.get(i);
      Particle other = particles.get(j);
      
      // make the particles seek each other
      particle.seek(other.pos);
      other.seek(particle.pos);
      
      // interact with each each other
      particle.interact(other, 2);
      
      // then update physics and display
      particle.update();
      particle.display();
      
      other.update();
      other.display();
    }
  }
}

class Particle {
  // 
  PVector pos;
  PVector velocity;
  PVector acceleration;
  float maxforce;
  float maxspeed;
  float r = 15;
  boolean interacting = false;
  float pulseSpeed;

  int id;

  float iradius = 0.0;
  float radius = 50.0;
  color colEllipse = color (random(255), 0, random(255)); 

  Particle(int x, int y, 
    int id_) {
    acceleration = new PVector(0, 0);
    velocity = new PVector(0, 0);
    pos = new PVector(x, y);
    maxspeed = 2.0;
    maxforce = 0.01;

    id = id_;

    // we can make the pulse of #0 of different speed
    if (id==0) 
      pulseSpeed=0.5;
    else pulseSpeed=0.9;
    //
  }  // end Particle constructor

  void applyForce(PVector force) {
    acceleration.add(force);
  }

  void seek(PVector target) {
    PVector desired = PVector.sub(target, pos);
    desired.normalize();
    desired.mult(maxspeed);
    PVector steer = PVector.sub(desired, velocity);
    steer.limit(maxforce);
    applyForce(steer);
  }

  // if the particles come within a certain distance
  // then interact by pulsing a circle.
  // The pulse effect should be a circle that grows until
  // it reaches a set radius, then disappears.

  // The pulsing circle will be centered at the particle's
  // x,y coordinates at each step.
  void interact(Particle other, float radius) {
    //if (id == other.id) {
    //    continue; // skip
    //}
    
    float d = PVector.dist(pos, other.pos);

      // trigger the interaction.
    if (d <= radius) {
        interacting = true;
        other.interacting = true;
        
        iradius = 0;
        other.iradius = 0;
    } // if
  } // end interact function.

  void update() {
    velocity.add(acceleration);
    velocity.limit(maxspeed);
    pos.add(velocity);
    acceleration.mult(0);
  }

  void display() {
    fill(colEllipse);
    noStroke(); 
    ellipse(pos.x, pos.y, 
      r, r);

    if (interacting) {
      if (iradius < radius) {
        noFill();
        stroke(255, 255, 0);
        ellipse(pos.x, pos.y, 
          iradius, iradius);
        iradius += pulseSpeed;
      } else {
        interacting = false;
      }
    }
  } // end display function.
  //
} // end Particle class.
//

No, this is very wrong…

The nested for-loops is ONLY for the question of collision, NOT for the other parts of draw…

      // interact with each each other
      particle.interact(other, 2);

(the consideration is mainly for many particles, with 2 particles it doesn’t matter)

You did rewrite interact() - basically without a for loop, Well done.

  Particle pt; 

  for (int i=0; i<particles.size()-1; i++) {
   pt  = particles.get(i)
    for (int j=i+1; j<particles.size(); j++) {
      // interact with each each other
      pt.interact(particles.get( j ), 25);
    } 
  }

Got it. Here is now my draw() function

void draw() {
  background(0);

  // make particles seek and interact with each other  
  for (int i=0; i<particles.size()-1; i++) {
    for (int j=i+1; j<particles.size(); j++) {
      Particle particle = particles.get(i);
      Particle other = particles.get(j);
      
      particle.seek(other.pos);
      other.seek(particle.pos);
      
      particle.interact(other, 25);
    }
  }

  // update physics and display
  for (Particle particle : particles) {
    particle.update();
    particle.display();
  }
}

much better

Well done

Did you try with 20 particles?

Chrisir

Yes. With the current code, because the iradius is reset within the interact() function the effect keeps resetting, and therefore it doesn’t look like any effect is happening at all.

Next step is to focus on these lines

iradius = 0;
other.iradius = 0;

in here

void interact(Particle other, float radius) {

    float d = PVector.dist(pos, other.pos);

      // trigger the interaction.
    if (d <= radius) {
        interacting = true;
        other.interacting = true;
        
        iradius = 0;
        other.iradius = 0;
    } // if
  } // end interact function.

and introduce some logic where if a particle effect is currently in progress, don’t reset.

something like

 if (d <= radius) {
   
   if( !interacting) {
       interacting = true;
       iradius = 0;
  }

   if( !other.interacting) {
       other.interacting = true;
       other.iradius = 0;
  }
  //
}

The ! means NOT

1 Like

That does the trick! @Chrisir thank you for your help, tips, and guidance with this. I learned a lot through the process.

1 Like