FAQ
 
 
Cover  \ Exhibition  \ Learning  \ Reference  \ Download  \ Discourse   
    Examples \ Tutorials \ Courses & Workshops
 
   
 
 
Examples for Processing (BETA) version 91+. 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.



Multiple Particle Systems
Daniel Shiffman <http://www.shiffman.net>

Click the mouse to generate a burst of particles at mouse location

Each burst is one instance of a particle system
with Particles and CrazyParticles (a subclass of Particle)
Note use of Inheritance and Polymorphism here

   
// Multiple Particle Systems 
// Daniel Shiffman <http://www.shiffman.net> 

// Created 2 May 2005 
 
ArrayList psystems; 
 
void setup() { 
  size(200,200); 
  framerate(30); 
  colorMode(RGB,255,255,255,100); 
  psystems = new ArrayList(); 
  smooth(); 
} 
 
void draw() { 
  background(0); 
 
  // Cycle through all particle systems, run them and delete old ones 
  for (int i = psystems.size()-1; i >= 0; i--) { 
    ParticleSystem psys = (ParticleSystem) psystems.get(i); 
    psys.run(); 
    if (psys.dead()) { 
      psystems.remove(i); 
    } 
  } 
 
} 
 
// When the mouse is pressed, add a new particle system 
void mousePressed() { 
  psystems.add(new ParticleSystem(int(random(5,25)),new Vector3D(mouseX,mouseY))); 
} 
 
 
// A subclass of Particle 
 
// Created 2 May 2005 
 
class CrazyParticle extends Particle { 
 
  // Just adding one new variable to a CrazyParticle 
  // It inherits all other fields from "Particle", and we don't have to retype them! 
  float theta; 
 
  // The CrazyParticle constructor can call the parent class (super class) constructor 
  CrazyParticle(Vector3D l) { 
    // "super" means do everything from the constructor in Particle 
    super(l); 
    // One more line of code to deal with the new variable, theta 
    theta = 0.0; 
 
  } 
 
  // Notice we don't have the method run() here; it is inherited from Particle 
 
  // This update() method overrides the parent class update() method 
  void update() { 
    super.update(); 
    // Increment rotation based on horizontal velocity 
    float theta_vel = (vel.x * vel.magnitude()) / 10.0f; 
    theta += theta_vel; 
  } 
 
  // Override timer 
  void timer() { 
    timer -= 0.5; 
  } 
  
  // Method to display 
  void render() { 
    // Render the ellipse just like in a regular particle 
    super.render(); 
 
    // Then add a rotating line 
    pushMatrix(); 
    translate(loc.x,loc.y); 
    rotate(theta); 
    stroke(255,timer); 
    line(0,0,25,0); 
    popMatrix(); 
  } 
} 
 
 
 
 
 
// A simple Particle class 
 
class Particle { 
  Vector3D loc; 
  Vector3D vel; 
  Vector3D acc; 
  float r; 
  float timer; 
 
  // One constructor 
  Particle(Vector3D a, Vector3D v, Vector3D l, float r_) { 
    acc = a.copy(); 
    vel = v.copy(); 
    loc = l.copy(); 
    r = r_; 
    timer = 100.0; 
  } 
  
  // 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); 
    noStroke(); 
    fill(255,timer); 
    ellipse(loc.x,loc.y,r,r); 
  } 
  
  // Is the particle still useful? 
  boolean dead() { 
    if (timer <= 0.0) { 
      return true; 
    } else { 
      return false; 
    } 
  } 
} 
 
 
// 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 birthed 
 
  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 CrazyParticle(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(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 Vector3D Class 
 
public class Vector3D { 
  public float x; 
  public float y; 
  public 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; 
  } 
  public float magnitude() { 
    return (float) Math.sqrt(x*x + y*y + z*z); 
  } 
 
  public Vector3D copy() { 
    return new Vector3D(x,y,z); 
  } 
 
  public Vector3D copy(Vector3D v) { 
    return new Vector3D(v.x, v.y,v.z); 
  } 
  
  public void add(Vector3D v) { 
    x += v.x; 
    y += v.y; 
    z += v.z; 
  } 
 
  public void sub(Vector3D v) { 
    x -= v.x; 
    y -= v.y; 
    z -= v.z; 
  } 
 
  public void mult(float n) { 
    x *= n; 
    y *= n; 
    z *= n; 
  } 
 
  public void div(float n) { 
    x /= n; 
    y /= n; 
    z /= n; 
  } 
 
  public void normalize() { 
    float m = magnitude(); 
    if (m > 0) { 
       div(m); 
    } 
  } 
 
  public void limit(float max) { 
    if (magnitude() > max) { 
      normalize(); 
      mult(max); 
    } 
  } 
 
  public float heading2D() { 
    float angle = (float) Math.atan2(-y, x); 
    return -1*angle; 
  } 
 
  public Vector3D add(Vector3D v1, Vector3D v2) { 
    Vector3D v = new Vector3D(v1.x + v2.x,v1.y + v2.y, v1.z + v2.z); 
    return v; 
  } 
 
  public Vector3D sub(Vector3D v1, Vector3D v2) { 
    Vector3D v = new Vector3D(v1.x - v2.x,v1.y - v2.y,v1.z - v2.z); 
    return v; 
  } 
 
  public Vector3D div(Vector3D v1, float n) { 
    Vector3D v = new Vector3D(v1.x/n,v1.y/n,v1.z/n); 
    return v; 
  } 
 
  public Vector3D mult(Vector3D v1, float n) { 
    Vector3D v = new Vector3D(v1.x*n,v1.y*n,v1.z*n); 
    return v; 
  } 
 
  public 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); 
  } 
 
} 
 
 
 
 







   
  Processing is an open project initiated by Ben Fry and Casey Reas  
  © Info