This example is for Processing (BETA) version 149+. If you have a previous version, use the examples included with your software. If you see any errors or have comments, please let us know.
Simple Particle System by Daniel Shiffman.
Particles are generated each cycle through draw(), fall with gravity and fade out over time A ParticleSystem object manages a variable size (ArrayList) list of particles.
ParticleSystem ps;
void setup() {
size(640, 360);
colorMode(RGB, 255, 255, 255, 100);
ps = new ParticleSystem(1,new Vector3D(width/2,height/2,0));
smooth();
}
void draw() {
background(0);
ps.run();
ps.addParticle(mouseX,mouseY);
}
// 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
Vector3D origin; // An origin point for where particles are born
ParticleSystem(int num, Vector3D v) {
particles = new ArrayList(); // Initialize the arraylist
origin = v.copy(); // Store the origin point
for (int i = 0; i < num; i++) {
particles.add(new Particle(origin)); // Add "num" amount of particles to the arraylist
}
}
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);
}
}
}
void addParticle() {
particles.add(new Particle(origin));
}
void addParticle(float x, float y) {
particles.add(new Particle(new Vector3D(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;
}
}
}
// Simple Vector class
class Vector3D {
float x;
float y;
float z;
Vector3D(float x_, float y_, float z_) {
x = x_;
y = y_;
z = z_;
}
Vector3D(float x_, float y_) {
x = x_;
y = y_;
z = 0f;
}
Vector3D() {
x = 0f;
y = 0f;
z = 0f;
}
void setX(float x_) {
x = x_;
}
void setY(float y_) {
y = y_;
}
void setZ(float z_) {
z = z_;
}
void setXY(float x_, float y_) {
x = x_;
y = y_;
}
void setXYZ(float x_, float y_, float z_) {
x = x_;
y = y_;
z = z_;
}
void setXYZ(Vector3D v) {
x = v.x;
y = v.y;
z = v.z;
}
float magnitude() {
return (float) Math.sqrt(x*x + y*y + z*z);
}
Vector3D copy() {
return new Vector3D(x,y,z);
}
Vector3D copy(Vector3D v) {
return new Vector3D(v.x, v.y,v.z);
}
void add(Vector3D v) {
x += v.x;
y += v.y;
z += v.z;
}
void sub(Vector3D v) {
x -= v.x;
y -= v.y;
z -= v.z;
}
void mult(float n) {
x *= n;
y *= n;
z *= n;
}
void div(float n) {
x /= n;
y /= n;
z /= n;
}
/* float dot(Vector3D v) {
//implement DOT product
}*/
/* Vector3D cross(Vector3D v) {
//implement CROSS product
}*/
void normalize() {
float m = magnitude();
if (m > 0) {
div(m);
}
}
void limit(float max) {
if (magnitude() > max) {
normalize();
mult(max);
}
}
float heading2D() {
float angle = (float) Math.atan2(-y, x);
return -1*angle;
}
Vector3D add(Vector3D v1, Vector3D v2) {
Vector3D v = new Vector3D(v1.x + v2.x,v1.y + v2.y, v1.z + v2.z);
return v;
}
Vector3D sub(Vector3D v1, Vector3D v2) {
Vector3D v = new Vector3D(v1.x - v2.x,v1.y - v2.y,v1.z - v2.z);
return v;
}
Vector3D div(Vector3D v1, float n) {
Vector3D v = new Vector3D(v1.x/n,v1.y/n,v1.z/n);
return v;
}
Vector3D mult(Vector3D v1, float n) {
Vector3D v = new Vector3D(v1.x*n,v1.y*n,v1.z*n);
return v;
}
float distance (Vector3D v1, Vector3D v2) {
float dx = v1.x - v2.x;
float dy = v1.y - v2.y;
float dz = v1.z - v2.z;
return (float) Math.sqrt(dx*dx + dy*dy + dz*dz);
}
void display(float x, float y, float scayl) {
pushMatrix();
float arrowsize = 4;
// Translate to location to render vector
translate(x,y);
// stroke(255);
// Call vector heading function to get direction (note that pointing up is a heading of 0) and rotate
rotate(heading2D());
// Calculate length of vector & scale it to be bigger or smaller if necessary
float len = magnitude()*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 simple Particle class
class Particle {
Vector3D loc;
Vector3D vel;
Vector3D acc;
float r;
float timer;
// Another constructor (the one we are using here)
Particle(Vector3D l) {
acc = new Vector3D(0,0.05,0);
vel = new Vector3D(random(-1,1),random(-2,0),0);
loc = l.copy();
r = 10.0;
timer = 100.0;
}
void run() {
update();
render();
}
// Method to update location
void update() {
vel.add(acc);
loc.add(vel);
timer -= 1.0;
}
// Method to display
void render() {
ellipseMode(CENTER);
stroke(255,timer);
fill(100,timer);
ellipse(loc.x,loc.y,r,r);
vel.display(loc.x,loc.y,10);
}
// Is the particle still useful?
boolean dead() {
if (timer <= 0.0) {
return true;
} else {
return false;
}
}
}


