import ddf.minim.signals.*;
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;


boolean virgin = true;

float liney = 150;
float burliney = 10;
yoyo y;
cloud c;
HashSet frogs = new HashSet();;
HashSet deadfrogs = new HashSet();



int frogcount = 3;
AudioSnippet chomp[] = new AudioSnippet[4];
AudioSnippet burn[] = new AudioSnippet[4];

int fps = 50;

void setup(){

  size(400,400);
    Minim.start(this);
  frameRate(50);
  textFont(loadFont("AkbarPlain-30.vlw"),30);
c = new cloud(200,20,"cloud.gif");

  y = new yoyo(229,200,"yoyo.gif");

 deadfrogs= new HashSet();


 for(int i = 0; i < chomp.length; i++){
     chomp[i] =  Minim.loadSnippet("ribbit"+(i+1)+".mp3");
     burn[i] =  Minim.loadSnippet("burn"+(i+1)+".mp3");
  }

  
  

}

int timer; int smalltimer;
int score;
boolean gamerunning;
void gameoff(){
    gamerunning = false;
}
void gameon(){
  virgin = false;
         deadfrogs = new HashSet();
 frogs= new HashSet();
    for(int i = 0; i < frogcount;i++){
    addFrog();
  }
gamerunning = true;
timer = 30;
smalltimer = 0;
score = 0;
}


void stop()
{

    for(int i = 0; i < chomp.length; i++){
     chomp[i].close();
     burn[i].close();
  }
  super.stop();
}

int ctr;

void mouseClicked(){
   if(! gamerunning){
      gameon();
   } 
}


void draw(){
  background(128,128,200);
  //m.x = mouseX;
  // m.y = mouseY;

smalltimer++;
if(smalltimer >= fps){
   smalltimer = 0;
   timer--; 
} 
if(timer == 0){
   gameoff(); 
}

stroke(100,100,170);
line(0,liney,400,liney);

stroke(170,100,100);
line(0,burliney,400,burliney);


  ctr++;
  if(ctr % 50 == 0){
    //m.changeframe(m.currentframe==0?1:0); 
  }
 fill(0,128,0);  
 
if(! gamerunning){
  text("click to play",20,70);
  text("BASHO 2",100,100);
  text("use magic sun yoyo",100,180);
  text("to bash froggies",100,210);
  text("to heavenly award",100,240);
  text("(not to be letting",100,270);
  text("(froggy hit high sky",100,300);
  text("  of fire!) ",100,330);

  if(!virgin){
       text("last score:"+score,200,380);
  }
 
} else {
 text("time:"+timer,20,380);
 text("froggies:"+score,200,380);
 
}

c.move();
c.bounds();
  
  y.move();

  y.bounds();

  y.draw();

c.draw();

  int howmanyToAdd = 0;

  Iterator it = frogs.iterator();
  while(it.hasNext()){
    frog f = (frog)it.next();
    f.bounds();
    f.move();
    
    if(c.overlap(f)){
       it.remove(); 
        howmanyToAdd ++;
           int sfx = int(random(chomp.length));
       chomp[sfx].rewind();      chomp[sfx].play();
       
       if(gamerunning){score++;}
       
    } else {
    
    if(f.y < burliney){
           int sfx = int(random(burn.length));
       burn[sfx].rewind();      burn[sfx].play();
       if(gamerunning){score--;}

      deadfrogs.add(new deadfrog(f));
      it.remove();
    }
    }

    f.draw();
    if(y.overlap(f)){
    //frog df = new frog(f.x,f.y,"deadfrog.gif");
    //deadfrogs.add(df);
    f.xs = y.xs;
    f.ys = y.ys;
   // it.remove();
    
    
    }
  }


it = deadfrogs.iterator();
    while(it.hasNext()){
    deadfrog df = (deadfrog)it.next();
      df.move();
      df.draw();
      if(df.y > 400){
          howmanyToAdd++;
          it.remove();
      }
    }

if(gamerunning){
for (int i = 0; i <  howmanyToAdd ;i++){
  addFrog(); 
}
}



}


class cloud extends sprat{
  float xdir,cx,cy;  
  cloud(int x, int y, String s){
      super(x,y,s);
  cx = x;
  cy = y;
  xdir = 3;
  }
  
  void move(){
    cx += xdir; 
    x = round(cx);
  }
  void bounds(){
  if(cx <0){
    cx = 0;
    xdir = 3; 
    move();
  }
  if(cx > 320){
    cx =  320;
    xdir = -3; 
    move();
  }
  }
  
}


class deadfrog extends sprat{
    float fx,fy,xs,ys;
  deadfrog(int x, int y, String s){
    super(x,y,s);
    fy = y; 
    fx = x;

  }
  deadfrog(frog f){
    this(f.x,f.y,"frogdead.gif");
  }
  void move(){
    ys += .1;
    fy+=ys;
    fx+=xs;
    x = round(fx);
    y = round(fy);
  }
  
}

class frog extends sprat{
  frog(int x, int y, String s){
    super(x,y,s);
    fy = y; 
    fx = x;

  }
  float xs,ys, fy,fx;
  float sz = 40;
  void move(){
    ys += .1;
    fy+=ys;
    fx+=xs;
    x = round(fx);
    y = round(fy);
  }

  void bounds(){
     if(fx < 0){
        xs = abs(xs);
        fx = 0 ;
     } 
     if(x+sz+sz >= 400){
        xs = -abs(xs);
        fx = 400 - sz - sz;
     } 
     if(y < 0){
        ys = abs(ys)/2;
        
        fy = 0;
     } 
     if(y+sz >= 400){
        ys = -abs(ys);
        fy = fy - sz;
     } 
  }
}



class yoyo extends sprat{
  float fx,fy,xs,ys;
  boolean mOn = true;
  yoyo(int x, int y, String s){
    super(x,y,s);
  }
  float useY;
  
  void bounds(){
     if(fy < liney){
        fy = liney;
        ys = abs(ys);
     } 
     y = round(fy);
     
  }
  
  
  void move(){
    ys += .8; //gravity
    if(mOn) {
      xs += ( mouseX - (fx+20)) / 10.0; 
       useY = mouseY;
      //if(useY < 100) { useY = 100; }
      ys += ( useY - (fy+20)) / 10.0;
    }
    // if(mOn){
    xs *= .8;
    ys *= .8;
    // }
    fx += xs;
    fy += ys;
    y = round(fy);
    x = round(fx);
  }
  void draw(){
    stroke(0);
    strokeWeight(2);
    line(mouseX,useY,fx+20,fy+20);
    super.draw();
  }


}



class sprat{
  int x,y,w,h;
  int framecount;
  int currentframe;
  PImage img[];
  sprat(int px,int py, String imgname){
    String s[] = new String[1];
    s[0] = imgname;
    init(px,py,s);
  } 
  sprat(int px,int py, String[] imgname){
    init(px,py,imgname);
  } 

  void init (int px,int 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 - x;
    int ry = py - y;
    return img[currentframe].pixels[rx + (ry * w)];
  }

  boolean overlap(sprat other){
    intRange vOverlap = spratOverlapVert(other);
    intRange hOverlap = spratOverlapHoriz(other);
    if(vOverlap == null || hOverlap == null){
      return false;
    }
    //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; 
        }
      }
    }

    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 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;
  }

}





void addFrog(){
  //every dude is launched  from one of the 2 walls
  float posOnWall = liney + random(400-liney);
  float mainSpeed = random(10);
  //speed parallel to wall
  float lateralSpeed = 3;

  float x=0,y=0, xs=0,ys=0;
  int r =   int(random(2));
  if(r == 0){ //leftwall
    x = -40;
    y = posOnWall;
    xs = mainSpeed;
    ys = lateralSpeed;
  }
  if(r == 1){ //rightwall
    x = 40;
    y = posOnWall;
    xs = -1*mainSpeed;
    ys = lateralSpeed;
  }


  frog f = new frog(round(x),round(y),"froglive.gif");
  f.xs = xs;
  f.ys = ys;
  
  frogs.add(f);
}