ParticleSystem ps;
int i = 0;
PImage feed;
int palette[] = new int[5];
void setup() {
size(512, 512, P2D);
colorMode(RGB, 255);
smooth();
ps = new ParticleSystem(1000);
// http://www.colourlovers.com/palette/1014170
palette[0] = color(236,219,113);
palette[1] = color(153,115,74);
palette[2] = color(6,29,37);
palette[3] = color(0,80,61);
palette[4] = color(17,41,22);
background(palette[4]);
}
void draw() {
ps.run();
// this will stretch the image and blur it, with feedback
feed = get(1,1,width-2,height-2);
image(feed,0,0,width,height);
// add atraction
if (mousePressed && this.mouseButton == LEFT){
ps.addAttraction(mouseX,mouseY, 2.2f);
}
// add repulsion
if (mousePressed && this.mouseButton == RIGHT){
ps.addRepulsion(mouseX,mouseY,-2.2f);
}
ps.addFriction(-0.1f);
if (keyPressed) {
saveFrame();
}
}
// A simple Particle class
class Particle {
PVector loc;
PVector vel;
PVector acc;
float timer;
color c;
float mass;
// Another constructor (the one we are using here)
Particle(PVector l) {
acc = new PVector(0, 0, 0);
loc = l.get();
timer = random(255.0f);
c = (5*(int)timer)/255;
mass = (c+1)*5;
float absVel = 25-(timer/10);
vel = new PVector(random(-1,1)*absVel, random(-1,1)*absVel, 0);
}
void run() {
update();
render();
}
// Method to update location
void update() {
vel.add(acc);
loc.add(vel);
timer -= 0.1;
acc.mult(0);
}
// Method to display
void render() {
stroke(palette[4-c],timer);
displayVector(vel, loc.x, loc.y, 10);
}
// Is the particle still useful?
boolean dead() {
if (timer <= 0.0) {
return true;
}
else {
return false;
}
}
void addForce(PVector f) {
f.div(mass);
acc.add(f);
}
void displayVector(PVector v, float x, float y, float scayl) {
pushMatrix();
float arrowsize = 4;
// Translate to location to render vector
translate(x, y);
// Call vector heading function to get direction (note that pointing
// up is a heading of 0) and rotate
rotate(v.heading2D());
// Calculate length of vector & scale it to be bigger or smaller if
// necessary
float len = v.mag() * scayl;
// Draw three lines to make an arrow (draw pointing up since we've
// rotate to the proper direction)
line(0, 0, len, 0);
//line(len, 0, len - arrowsize, +arrowsize / 2);
//line(len, 0, len - arrowsize, -arrowsize / 2);
popMatrix();
}
}
// A class to describe a group of Particles
// An ArrayList is used to manage the list of Particles
class ParticleSystem {
ArrayList particles; // An arraylist for all the particles
PVector origin; // An origin point for where particles are born
ParticleSystem(int num, PVector v) {
particles = new ArrayList(); // Initialize the arraylist
origin = v.get(); // Store the origin point
for (int i = 0; i < num; i++) {
particles.add(new Particle(origin)); // Add "num" amount of
}
}
ParticleSystem(int num) {
particles = new ArrayList(); // Initialize the arraylist
// particles born at random location
for (int i = 0; i < num; i++) {
particles.add( new Particle(new PVector(random(0,width), random(0,height))));
}
}
public void addFriction(float friction) {
for (int i = particles.size() - 1; i >= 0; i--) {
Particle p = (Particle) particles.get(i);
PVector f = PVector.mult(p.vel, friction);
p.addForce(f);
}
}
public void addAttraction(int x, int y, float attraction) {
for (int i = particles.size() - 1; i >= 0; i--) {
Particle p = (Particle) particles.get(i);
PVector mouseLoc = new PVector(x,y,0);
PVector diff = PVector.sub(mouseLoc,p.loc);
diff.normalize();
diff.mult(attraction);
p.addForce(diff);
}
}
public void addRepulsion(int x, int y, float repulsion) {
for (int i = particles.size() - 1; i >= 0; i--) {
Particle p = (Particle) particles.get(i);
PVector mouseLoc = new PVector(x,y,0);
PVector diff = PVector.sub(mouseLoc,p.loc);
diff.normalize();
diff.mult(repulsion);
p.addForce(diff);
}
}
// Method to add a force vector to all particles currently in the system
void addForce(PVector dir) {
for (int i = particles.size()-1; i >= 0; i--) {
Particle p = (Particle) particles.get(i);
p.addForce(dir);
}
}
void run() {
// Cycle through the ArrayList backwards b/c we are deleting
for (int i = particles.size() - 1; i >= 0; i--) {
Particle p = (Particle) particles.get(i);
p.run();
if (p.dead()) {
particles.remove(i);
ps.addParticle(random(0,width), random(0,height));
}
}
}
void addParticle() {
particles.add(new Particle(origin));
}
void addParticle(float x, float y) {
particles.add(new Particle(new PVector(x, y)));
}
void addParticle(Particle p) {
particles.add(p);
}
// A method to test if the particle system still has particles
boolean dead() {
if (particles.isEmpty()) {
return true;
}
else {
return false;
}
}
}
Virtual particles are created, and destroyed, with a time dependent mass. You can attract or repel, them, with the mouse, but the field is filled with uncertainty...