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);
}
//Add a new particle
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));
}
}
class Particle{
PVector loc; //2d vector storing x and y locations
PVector acc; //rate of acceleration
PVector vel; //controlling direction
float r; //radius of particle
float timer; //particle lifetime
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);
acc.add(force);
}
//main
void run(ArrayList parts){
bounds();
applyAttraction(parts);
update();
render();
}
//update vector values
void update(){
vel.add(acc);
vel.limit(velLim);
loc.add(vel);
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
boolean dead(){
if(timer <= 0.0){
return true;
}
else{
return false;
}
}
}
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();
font = loadFont("Monaco-12.vlw");
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);
}
}
Click/hold mousebutton to generate particles!
A second version, with thanks to kooogy of the p5forums for pointing out the obvious way to help speed up the sketch :)
Trying to learn how to implement attraction into particle systems - this code is a little bit cobbled together from some of my own sketches and Shiffman's Nature of Code tutorials. Trying to optimise it as I am sure there must be much more efficient ways to control attraction than I have used here.
http://hendersonmedia.wordpress.com
http://hendersonsix.com