firework.pjs

Your browser does not support Processing.js. Please upgrade to Firefox 3.5.
/** a firework particle */
class Firework {
  public float direction = 0; //direction of head
  int x = 20; //x coordinate
  int y = 20; //y coordinate
  public int velocity = 5; //speed of movement
  public float acc = 0.03; //increase of velocity
  public float directionInc = 0.03; //increase of direction (to right)
  public int energy = 10; //energy of the particle
  public int r = 255; //red
  public int g = 180; //green
  public int b = 255; //blue
  public int ri = 0; //increase of red
  public int gi = 0; //increase of green
  public int bi = 0; //increase of blue
  /** constructs a new Firework. */
  public Firework(int x, int y, int r, int g, int b) {
    this.x = x;
    this.y = y;

    this.r = r;
    this.g = g;
    this.b = b;
  }
  /** draw this particle */
  public void display() {
    //don't draw if this particle is exhausted.
    if (this.energy < 1) {
      return;
    }
    //draw the shape
    fill(this.r, this.g, this.b); //fill with the current color
    ellipse(this.x, this.y, this.energy, this.energy);
    //calculate the new location
    this.energy *= 0.95; //decrease energy
    this.velocity += this.acc; //increase velocity by acceleration
    this.direction += this.directionInc; //increase the direction

    //check borders
    if (this.x < 0 || this.y < 0 || this.x > width || this.y > height) {
      //bounce back
      this.direction = -this.direction * 2.1;
      this.directionInc = -this.directionInc;
      this.energy *= 0.8; //bouncing costs some energy
    }

    //move forward
    this.x += this.velocity * cos(this.direction);
    this.y += this.velocity * sin(this.direction) + 5 / this.energy; //there is gravity affecting it

    //add color value by the increment of color value
    this.r = constrain(this.r + this.ri, 0, 255);
    this.g = constrain(this.g + this.gi, 0, 255);
    this.b = constrain(this.b + this.bi, 0, 255);
  }
}

/** a firework, explodes when its energy got exhausted. */
class LaunchFirework {
  public Firework f; //the firework particle
  public boolean exploded = false; //true if it is exploded
  /** constructs a new firework. */
  public LaunchFirework(int x1, int y1, int x2, int y2, int r, int g, int b) {
    f = new Firework(x1, y1, random(58, 255), random(58, 255), random(58, 255));
    //some values are assigned randomly.
    f.ri = random(-2, 2);
    f.gi = random(-2, 2);
    f.bi = random(-2, 2);

    f.velocity = abs((x2 - x1) + (y2 - y1)) / 15; //calculate speed
    f.direction = atan2(y2 - y1, x2 - x1); //calculate direction
    f.directionInc = random(-0.02, 0.02);
    f.energy = random(17, 23);
    this.f = f;
  }
  /** draw the firework. */
  public void display() {
    if (!this.exploded) {
      if (this.f.energy < 5) {
        //explode it
        this.exploded = true; 
        add(this.f.x, this.f.y);
      } else {
        //show that tiny spark
        this.f.display();
      }
    }
  }
}

ArrayList particles = new ArrayList(); //all firework particles
//mouse positions...
int oldX = 0;
int oldY = 0;
//make a new LaunchFirework or just Firework particle
boolean explode = true;

//creates an explosion
void add(int x, int y) {
  int r = random(1, 8);
  //random amount of fireworks
  for (int i = 0; i < r; i ++) {
    int n = random(6, 24);
    for (int j = 0; j < n; j ++) {
      Firework f = new Firework(x, y, random(58, 255), random(58, 255), random(58, 255));
      //assign them randomly
      f.ri = random(-5, 5);
      f.gi = random(-5, 5);
      f.bi = random(-5, 5);
      f.direction += j * TWO_PI / n;
      f.velocity = i;
      //add it
      particles.add(f);
    }
  }
}

//launch a new firework
void launch(int x1, int y1, int x2, int y2) {
  particles.add(new LaunchFirework(x1, y1, x2, y2, random(50, 255), random(50, 255), random(50, 255)));
}

void mousePressed() {
  oldX = mouseX;
  oldY = mouseY;
}

//decide to launch a new firework
void mouseDragged() {
  explode = false;
}

//launch or explode now?
void mouseReleased() {
  if (explode) {
    add(oldX, oldY);
  } else {
    launch(oldX, oldY, mouseX, mouseY);
    explode = true;
  }
}

void setup() {
  size(1000, 800);
  smooth();
  noStroke();
  add(width / 2, height / 2);
}

void draw() {
  background(#000000, 80); //this gives a motion blur effect
  for (int i = 0; i < particles.length; i ++) {
    Object p = particles.get(i); //get this particle
    if (p instanceof Firework) {
      //draw the particle
      ((Firework) p).display();
      if (((Firework) p).energy < 3) {
        particles.remove(i); //remove exhausted particles
      }
    } else if (p instanceof LaunchFirework) {
      //keep launching the firework
      ((LaunchFirework) p).display();
        //remove exploded ones
      if (((Firework) p).exploded) {
        particles.remove(i);
      }
    }
  }
}