/*********************************
FIREWORKS
by Keith Pasko
12.6.04
for a fun "bug", uncomment the
fill and rect functions in draw
*********************************/
Explosion[] myExplosion;
int presstime;
int numParticles=700;
int maxExplosions=7;
int [] counter=new int[maxExplosions+2];
float xpos;
float ypos;
int numpressed;
int presscount;
color colur;
boolean active;
PImage beginImage;
void setup()
{
active=false;
beginImage=loadImage("beginImage.gif");
imageMode(CENTER);
size(600,300);
ellipseMode(CENTER_RADIUS);
myExplosion=new Explosion[maxExplosions+2];
framerate(60);
smooth();
noStroke();
colur=color(255,255,255);
}
void draw(){
//fill (10,10,20,160);
//rect (0,0,width,height);
if (active==true){
background (10,10,20);
if (numpressed<maxExplosions+1){
for (int i=0; i<numpressed;i++){
myExplosion[i].update();
myExplosion[i].display();
}
}else{
for (int i=0;i<maxExplosions-1;i++){
myExplosion[i].update();
myExplosion[i].display();
}
}
}else{
beginScreen();
}
}
void beginScreen()
{
image (beginImage,300,150);
}
void keyPressed()
{
if (key==32 && active==false){
active = true;
}
if (key=='1'){
colur=color (213,0,0);
}else if (key=='2'){
colur=color(253,167,167);
}else if (key=='3'){
colur=color(250,176,17);
}else if (key=='4'){
colur=color(253,255,95);
}else if (key=='5'){
colur=color(76,245,68);
}else if (key=='6'){
colur=color(124,243,250);
}else if (key=='7'){
colur=color(11,38,204);
}else if (key=='8'){
colur=color(196,151,231);
}else if (key=='9'){
colur=color (255,255,255);
}
}
void mousePressed()
{
presscount++;
if (presscount==2*maxExplosions+1){
presscount=presscount-maxExplosions;
}
if (presscount>maxExplosions+1){
counter[maxExplosions+1]=counter[presscount-maxExplosions-1];
counter [presscount-maxExplosions-1]=millis();
}else{
counter[presscount-1]=millis();
}
}
void mouseReleased()
{
numpressed++;
if (presscount>maxExplosions+1){
presstime=millis()-counter[presscount-maxExplosions-1];
}else{
presstime=millis()-counter[presscount-1];
}
xpos=mouseX;
ypos=mouseY;
color c=colur;
float mag=presstime/40;
mag=constrain(mag,6,15);
if (numpressed==2*maxExplosions+1){
numpressed=numpressed-maxExplosions;
}
if (numpressed>=maxExplosions+1){
myExplosion[maxExplosions+1]=myExplosion[numpressed-maxExplosions-1];
myExplosion[numpressed-maxExplosions-1]=new Explosion (xpos, ypos, mag,c);
}else{
myExplosion[numpressed-1]=new Explosion(xpos,ypos,mag,c);
}
}
///////////////////
// EXPLOSIONS //
///////////////////
class Explosion
{
float x1;
float y1;
float magnitude;
color c;
Particle[] myParticle;
Explosion(float xpos,float ypos, float mag, color col)
{
x1=xpos;
y1=ypos;
magnitude=mag;
c=col;
myParticle=new Particle[numParticles];
for (int i=0;i<numParticles;i++){
float ag;
float lif=random(.4,2.1);
float scl=random(.5,1.5);
float thet=random(0,PI);
float ph=random(TWO_PI);
float inits=random(.12*sq(mag),.20*sq(mag));
if (presscount>maxExplosions+1){
ag=(millis()-counter[presscount-maxExplosions-1]);
}else{
ag=(millis()-counter[numpressed-1]);
}
myParticle[i]=new Particle(scl,thet,ph,inits,lif,ag);
}
}
void update()
{
for (int i=0;i<numParticles;i++){
if (myParticle[i].z<210){
myParticle[i].update(x1,y1);
}
}
}
void display()
{
for (int i=0;i<numParticles;i++){
if (myParticle[i].z<210){
myParticle[i].display(x1,y1,c);
}
}
}
}
///////////////////
// PARTICLES //
///////////////////
class Particle
{
float x;
float y;
float z;
float s; //initial speed
float siz_max; //max particle size
float theta; //spherical coordinates - angle from z-axis
float phi; //spherical coordinates - rotation around y-axis
float life; //particle lifespan
float age; //how long the particle has lived
float vel3d; //instantaneous velocity in 3 dimensions
float dragcoef; //drag at any given time
float windcoef;
float gravcoef;
float siz; //size of particle (changable)
float op; //opacity
float drag=1; //drag force amount
float gravity=5; //gravity force amount
float wind=0; //wind force amount
float winddir=0; //wind direction
float e=2.178; // Euler's constant e
float sramp=.4; //age at which particles grow to regular size
Particle (float scl,float thet,float ph, float inits, float lif, float ag)
{
siz_max=scl;
theta=thet;
phi=ph;
s=inits;
life=lif;
age=ag;
}
void update(float x0,float y0)
{
if ((age/1000)>life){
op=0;
}
if((age/1000)>life){
op=((life-age/1000))*255;
}else{
op=255;
}
if (z>210){
op=0;
}
if ((age/1000)<sramp){
siz=((age/1000)/sramp)*siz_max;
}else{
siz=siz_max;
}
vel3d=sqrt((sq(s*sin(theta)*cos(phi))+sq(-s*cos(theta))+sq(s*sin(theta)*sin(phi))));
if (drag>0){
dragcoef=vel3d*(1-pow(e,(-drag*(age/1000))))/drag;
}else{
dragcoef=vel3d*(age/1000);
}
gravcoef=gravity*age/1000;
x+=dragcoef*s*sin(theta)*cos(phi)/vel3d;//+windcoef*cos(winddir);
y+=dragcoef*-s*cos(theta)/vel3d;//+gravcoef;
z=dragcoef*s*sin(theta)*sin(phi)/vel3d;//+windcoef*sin(winddir);
}
void display(float x0,float y0, color c)
{
push();
translate (x0+x,y0+y,z);
fill(red(c)+random(-30,30),green(c)+random(-30,30),blue(c)+random(-30,30),op);
ellipse(0,0,siz,siz);
pop();
}
}