bee b;

float cannonx = 20;
float cannony = 160;
float cannonrot = 0;
boolean cannonup; 
int shotcounter = 6;
HashSet shots = new HashSet();
HashSet bees = new HashSet();

int beecount = -1;
int watercount = -1;

void setup(){
  size(480,320);
  frameRate(30);
  noStroke();
}
void draw(){
  background(200,200,255);
/*
  if(beecount != bees.size()){
       beecount = bees.size();
     // println("beecount now "+beecount);
  }
  if(watercount != shots.size()){
       watercount = shots.size();
      println("watercount now "+watercount);
  }
*/
  shotcounter++;
  if(shotcounter >= 4){
    shotcounter = 0;
    shots.add(new shot(cannonx,cannony,cannonrot)); 
  }
  //add bees?
  if(random(0,100) < 5){
    bees.add(new bee(width+2,random(20,height-40),random(10,40)));

  }



  if(cannonup){
    // if(cannonrot > PI*7/8){
    cannonrot -= .075;
    // }
  } 
  else {
    if(cannonrot < PI/4){
      cannonrot += .075; 
    }
  }
  //   println(cannonrot);
  Iterator it;

  it = bees.iterator();
  while(it.hasNext()){
    bee b = (bee)it.next();
    b.move();
    b.draw(); 

    Iterator si = shots.iterator();
    while(si.hasNext()){
      shot s = (shot)si.next();
      if(s.overlap(b)){
        si.remove();
        b.addshot(s);
        s.addbee(b);
      }
    }
     if(b.y > height + b.h){
        it.remove() ;
     } else {
       if(b.x < 0 - 2*b.w){
          it.remove(); 
       }
     }
  }


  it = shots.iterator();
  while(it.hasNext()){
    shot s = (shot)it.next();
    s.move();
    s.draw(); 
    if(s.y > height){
      it.remove(); 
    }
  }

  pushMatrix();
  translate(cannonx,cannony);
  rotate(cannonrot);
  fill(128);
  rect(-10,-10,20,20);
  popMatrix();


}
shot s;
void keyPressed(){
  cannonup = true;
}
void keyReleased(){
  cannonup = false; 
}
void mousePressed(){
  cannonup = true;
}
void mouseReleased(){
  cannonup = false; 
}

class intRange{
  int min, max;
  intRange(int p1, int p2){
    min = p1<p2?p1:p2; 
    max = p1>p2?p1:p2; 
  }
}

class intWithRef implements Comparable{
  int val; 
  Object src;
  intWithRef(int pval,Object psrc){
    val = pval; 
    src = psrc;
  } 
  public int compareTo(Object o){
    return val - ((intWithRef)o).val;
  }

}




class sprat{
  float x,y,w,h;
  int framecount;
  int currentframe;
  PImage img[];

  sprat(float px,float py){
    x = px;
    y = py;
  }
  sprat(){
  }

  sprat(float px,float py, String imgname){
    String s[] = new String[1];
    s[0] = imgname;
    init(px,py,s);
  } 
  sprat(float px,float py, String[] imgname){
    init(px,py,imgname);
  } 

  void init (float px,float py, String[] imgname){
    x = px; 
    y = py; 
    img = new PImage[imgname.length];
    for(int i = 0; i < imgname.length; i++){
      img[i] = loadImage(imgname[i]);      
    }
    changeframe(0);
  } 
  void changeframe(int whatframe){
    currentframe = whatframe;
    w = img[currentframe].width;
    h = img[currentframe].height;
  }

  void draw(){
    image(img[currentframe],x,y);
  }

  //so we have a physical x and y on screen
  //find the pixel for this thing
  //WARNING no bounds checking
  color pixelAtPhysicalLocation(int px, int py){
    int rx = px - round(x);
    int ry = py - round(y);
    return img[currentframe].pixels[rx + (ry * round(w))];
  }

  boolean overlap(sprat other){
    intRange vOverlap = spratOverlapVert(other);
    intRange hOverlap = spratOverlapHoriz(other);
    if(vOverlap == null || hOverlap == null){
      return false;
    }

    if(img != null){
      //hrrm, why couldn't this be <= ????
      for(int a = hOverlap.min; a < hOverlap.max; a++){
        for(int b = vOverlap.min; b < vOverlap.max; b++){
          if(alpha(this.pixelAtPhysicalLocation(a,b)) > 128 && alpha(other.pixelAtPhysicalLocation(a,b)) > 128    ){
            return true; 
          }
        }
      }
    } 
    else {
      if(vOverlap != null && hOverlap != null){
        return true;
      } 
    }

    return false;
  }

  // to see if things overlap on one dimension
  // we sort the 4 points. if both points of 
  // one thing are lesser than both points of the other,
  // they can't be overlapping...
  intRange spratOverlapHoriz(sprat b){
    sprat a = this;
    intWithRef vals[] = new intWithRef[4];
    vals[0] = new intWithRef((int)a.x,a);
    vals[1] = new intWithRef((int)(a.x+a.w),a);
    vals[2] = new intWithRef((int)b.x,b);
    vals[3] = new intWithRef((int)(b.x+b.w),b);
    Arrays.sort(vals);
    if (vals[0].src == vals[1].src){
      return null; 
    }
    return new intRange(vals[1].val,vals[2].val);
  }

  intRange spratOverlapVert(sprat b){
    sprat a = this;
    intWithRef vals[] = new intWithRef[4];
    vals[0] = new intWithRef((int)a.y,a);
    vals[1] = new intWithRef((int)(a.y+a.h),a);
    vals[2] = new intWithRef((int)b.y,b);
    vals[3] = new intWithRef((int)(b.y+b.h),b);
    Arrays.sort(vals);
    if (vals[0].src == vals[1].src){
      return null; 
    }
    return new intRange(vals[1].val,vals[2].val);

  }

}

class bug extends sprat{
  bug(float px, float py, float pw, float ph){

    super(px,py);
    w = pw;
    h = pw;
  } 
}


class shot extends sprat{
  float xs,ys;
  shot(float px, float py, float rot){
    super(px,py);
    w = 10;
    h = 10;
    xs = 8.0*cos(rot);
    ys = 8.0*sin(rot);
  } 
  void move(){
    if(mybee == null){
      x += xs;
      y += ys;
      ys +=.1;
    } 
    else {
      x = mybee.x + xoff;
      y = mybee.y + yoff; 
    }
  }
  void draw(){
    fill(0,0,128,64);
    rect(x,y,w,h); 
  }
  bee mybee = null;
  float xoff, yoff;
  void addbee(bee b){
    mybee = b; 
    xoff = x - b.x;
    yoff = y - b.y;
  }

}

class bee extends bug {
  float winger = 0;
  float placer = 0;
  ;
  HashSet myshots = new HashSet();
  float xs;
  float ypull;
  bee(float px, float py, float sz){
    super(px,py,sz,sz);
    //between 10 and 40...
    xs = (-50 + sz)/10.0;
  }
  void move(){
    winger += .8;
    placer += .1;
    x += xs;
    y += sin(placer) * 2.5;
    y += 2.0 * myshots.size() ;
  }    
  void addshot(shot s){
    myshots.add(s); 
  }


  void draw(){
    noStroke();
    float u = w / 10;

    fill(0);
    rect(x,y+(h*9/20),w * 1.25, h / 10);
    fill(255,255,0);
    rect(x,y,w,h);
    fill(0);

    rect(x + 2*u, y, u*2, h);
    rect(x + 6*u, y, u*2, h);
    //wing
    fill(0,0,128,80);
    rect(x+4*u,y-(2*u)+(sin(winger) * 2* u),u*5,u*5);

    Iterator i = myshots.iterator();
    while(i.hasNext()){
      shot s = (shot)i.next();
      s.move();
      s.draw();  
    }
  }



}