boolean auto = true;




ArrayList<Heart> hearts = new ArrayList<Heart>();
ArrayList<Zoomer> zoomers = new ArrayList<Zoomer>();
void setup(){
   size(500,500); 
}
int ticksquiet;
void mousePressed(){
   zoomers.add(new Zoomer(mouseX,mouseY));
  auto = false;
   ticksquiet = 0; 
}

void draw(){
  
  if(auto){
     if(random(100) < 3){
        zoomers.add(new Zoomer(random(100,400),random(100,300)));
     } 
  } else {
    ticksquiet++;
    if(ticksquiet > 600) auto = true;
  }
  
  
  
  //frameRate(5);
  background(0);
  smooth();
  noStroke();
  strokeWeight(2);
 
  fill(200,0,0);/*
  arc(100,100,50,50,PI,2*PI); 
  arc(150,100,50,50,PI,2*PI); 
   //ellipse(150,100,50,50); 
   
   
  triangle(75,100,175,100,125,175);*/
  ArrayList <Zoomer>zoomersToKill = new ArrayList<Zoomer>();
   for(Zoomer z : zoomers){
      z.draw(); 
      if(z.step >= 1.0){
         hearts.add(new Heart(z.dx,z.dy));
        zoomersToKill.add(z); 
      }
   }
  zoomers.removeAll(zoomersToKill);
  
  for(Heart h : hearts){
     h.drawSmoke(); 
  }
  for(Heart h : hearts){
     h.drawSmoke(); 
  }
  for(Heart h : hearts){
     h.drawSparks(); 
  }
  for(Heart h : hearts){
     h.clearSmoke(); 
  }
  for(Heart h : hearts){
     h.clearSparks(); 
  }
//println(frameRate);
//saveFrame("heart_####.png");
}

class Heart{
   float sz =  50;
   float  x = 300, y = 100;
  ArrayList<Spark>  sparks = new ArrayList<Spark>();
  ArrayList<Smoke> smoke = new ArrayList<Smoke>();
    float ang = random(-PI,PI)/4.0;  
  Heart(float px, float py){
x = px;
y = py;
int HOWMANY = 8;
    for(int i = 0; i < HOWMANY; i++){
       float a = ang+random(PI,2*PI);
        float dang = 0;
        float mx = x - ((sz/2) * cos(dang+ang));
        float my = y - ((sz/2) * sin(dang+ang));
        sparks.add(new Spark(this,mx,my,cos(a),sin(a)));
   
   }
     for(int i = 0; i < HOWMANY; i++){
       float a = ang+random(PI,2*PI);
        float dang = PI;
        float mx = x - ((sz/2) * cos(dang+ang));
        float my = y - ((sz/2) * sin(dang+ang));
        sparks.add(new Spark(this,mx,my,cos(a),sin(a)));
     }
     for(int i = 0; i < HOWMANY; i++){
        float c = 2;
        float xs = -random(c);
        float ys = 1.5 * (c - abs(xs) );
        
convertAndAddSpark(xs,ys);
     }
     for(int i = 0; i < HOWMANY; i++){
        float c = 2;
        float xs = random(c);
        float ys = 1.5 * (c - abs(xs) );

convertAndAddSpark(xs,ys);

     }
  }

  void convertAndAddSpark(float xs, float ys){
        float oldmag = dist(xs,ys,0,0);
        float oldang = atan2(ys,xs);
        float newang = oldang+ang;
        xs = oldmag * cos(newang);
        ys = oldmag * sin(newang);

    sparks.add(new Spark(this,x,y,xs,ys));
 
  }
  
   void draw(){
     /*
      pushMatrix();
       translate(x,y);
       rotate(ang);
//       rotate(map(mouseX,0,250,-PI,PI));
       arc(0 - sz/2,0,sz,sz,PI,2*PI);
       arc(0 + sz/2,0,sz,sz,PI,2*PI);
       triangle(-sz,0,sz,0,0,sz*1.5);
     
       popMatrix(); 
     */ 
   }
   void drawSmoke(){
       for(Smoke s : smoke){
         s.draw(); 
       }
     
   }
   void drawSparks(){
      
       for(Spark s : sparks){
          s.move();
         s.draw(); 
       }
   }
   void clearSmoke(){
     ArrayList<Smoke> smokeToKill = new ArrayList<Smoke>();
        for(Smoke s : smoke){
          if(s.dead()){
             smokeToKill.add(s); 
          }
        }
        smoke.removeAll(smokeToKill);
     
   }
   void clearSparks(){
     ArrayList<Spark> sparksToKill = new ArrayList<Spark>();
        for(Spark s : sparks){
          if(s.dead()){
             sparksToKill.add(s); 
          }
        }
        sparks.removeAll(sparksToKill);
   }
   
   
  void addSmoke(Smoke s){
      smoke.add(s);
  }
}

class Spark{
  float x, y, xs, ys;
  Heart heart;
  Spark(Heart pheart , float px, float py, float pxs, float pys){
     x = px; y = py; xs = pxs/2; ys = pys/2; 
  heart = pheart;  
}


  void move(){
    x += xs;
    y += ys; 
    ys += .01;
    life ++;
  }

  boolean dead(){
     if(life < 60) return false;
    if(random(abs(60-life)) > 80) return true;
   return false; 
  }

  boolean lit = true;
  
  int life;
  void draw(){
    if(lit){
      fill(255,0,0);
      if(random(100) < 10)      heart.addSmoke(new Smoke(this));
    } else {
       fill(100,0,0);
    }
        ellipse(x,y,5,5);
  
  if(life > 60){
     if(random(100) < 10) lit = false; 
  }
  

}

  
}


class Smoke{
  float x,y;
  float health;
   Smoke(Spark s){
      x = s.x;
      y = s.y;
      health=random(80,100)/2;
   } 
   boolean dead(){
      return health < 0; 
   }
   void draw(){
       fill(health*2.5,health*1.5,health*1.5);
    health -= .35;
        ellipse(x,y,3,3); 
   }
}

class Zoomer{
 float dx,dy;
 float step = 0;
  Zoomer(float px, float py){
    dx = px;
    dy = py;
 } 
 void draw(){
   float x = lerp(250,dx,step);
    float y = lerp(500,dy,step);
 
   //stroke(100,0,0);
//  line(250,500,x,y);
  //noStroke();
   fill(255,0,0);
    ellipse(x,y,5,5);
    step += .03;
 }
 
 
}