### Processing: Particle System and Attractive Forces

05Oct10

Another simple enough sketch I have been working on while trying to learn more about vectors and simulating forces in processing. It consists of a particle system in which all the particles that come into close contact become magnetised to each other. This results in some interesting emergent patterns, such as spirals, circular shapes that travel one-dimensionally, and explosions as the particles begin to die out.

Daniel Shiffman’s Nature of Code website was very helpful in building the sketch and for learning about some of the basic theory behind vectors and natural algorithms.

Play with the applet here.

Commented sourcecode posted below:

```ParticleSystem ps;
PFont font;

void setup(){
size(800, 500, JAVA2D);
background(0);
ps = new ParticleSystem(1, new PVector(width/2, height/2, 0), 2, 5, 0.1, 255); //create new particle system ArrayList
smooth();

textFont(font, 12);
}

void draw(){
fill(0, 3);
rect(0, 0, width, height); //show particle trails

ps.run();

if(mousePressed){
ps.addParticle(mouseX, mouseY, 2, 5, 0.1, 255);
}
}

//Another class to handle the addition and removal of the individual particle objects from the ArrayList
class ParticleSystem{
ArrayList parts;
PVector origin;

//Constructor
ParticleSystem(int num, PVector v, float r, float mass, float grav, float timer){
parts = new ArrayList();
origin = v.get();
for(int i=0; i<num; i++){
parts.add(new Particle(origin, r, mass, grav, timer));
}
}

void run(){
for(int i=parts.size()-1; i>=0; i--){
Particle p = (Particle) parts.get(i);
p.run(parts); //run all the main actions for every particle in the ArrayList
if(p.dead()){ //if particle p timer is = 0, remove it from the ArrayList
parts.remove(i);
}
}

//display how many particles are alive
fill(0);
rect(width-120, height-40, width, height);
fill(255);
text("Particles: "+parts.size(), width-100, height-16);
}

void addParticle(float x, float y, float r, float mass, float grav, float timer){
parts.add(new Particle(new PVector(x, y), r, mass, grav, timer));
}
}

//Set up individual particle object
class Particle{
PVector loc;   //2d vector storing x and y locations
PVector acc;   //rate of acceleration
PVector vel;   //controlling direction
float mass;    //"weight" of particle, need for attraction algorithm
float velLim;  //limit the speed at which the particles can travel
float g;       //gravity constant
ArrayList parts;

Particle(PVector l, float _r, float _mass, float _grav, float _timer){
loc = l.get(); //x and y values
acc = new PVector(random(0, 2), random(0, 2), 0);  //set initial acceleration
vel = new PVector(random(-2, 2), random(-1, 1), 0); //set initial velocity
r = _r;
mass = _mass;
g = _grav;
timer = _timer;
velLim = 5.0;
}

void applyAttraction(ArrayList parts){
//compare location values between different particles in the arraylist
for(int i=0; i<parts.size();i++){
Particle p1 = (Particle)parts.get(i);
for(int j=i+1;j<parts.size();j++){
Particle p2 = (Particle)parts.get(j);

PVector dir = PVector.sub(p1.loc, p2.loc);
float d = dir.mag();
dir.normalize();

//calculate strength of attraction
float force = (g * p1.mass * p2.mass) / (d*d);
dir.mult(force);

p2.applyForce(dir);
dir.mult(-1.0);
p1.applyForce(dir);
}
}
}

//used to apply the attraction force
void applyForce(PVector force){
force.div(mass);
}

//main
void run(ArrayList parts){
bounds();
applyAttraction(parts);
update();
render();
}

//update vector values
void update(){
vel.limit(velLim);
acc.mult(0);
timer -= 1.0;
}

//bounces particles off canvas edge
void bounds(){
if(loc.y > height || loc.y < 0){
vel.y *= -1;
}
if(loc.x > width || loc.x < 0){
vel.x *= -1;
}
}

//set the visual characteristics of the individual particles here
void render(){
ellipseMode(CENTER);
noStroke();
fill(255,  timer);
ellipse(loc.x, loc.y, r, r);
}

//check if the particle's timer is 0
if(timer <= 0.0){
return true;
}
else{
return false;
}
}
}
```