import processing.core.*; import java.applet.*; import java.awt.*; import java.awt.image.*; import java.awt.event.*; import java.io.*; import java.net.*; import java.text.*; import java.util.*; import java.util.zip.*; public class sugardum extends PApplet {plum m;
gift boxes[];

boolean gameover = false;
long wintime;

long timestart;





movesprat star;
int BOXCOUNT = 30;
public void setup(){
  frameRate(30);
  size(400,400);

  textFont(loadFont("AlbaSuper-48.vlw"),24);
  ellipseMode(CENTER);

  startgame();
}


public void startgame(){
    timestart = millis();  
   //movesprat(int px,int py, String imgname, float pmass, float pfriction, float prebound){
  star = new movesprat(PApplet.parseInt(random(300)),200,"star.gif",10.0f,.99f,.5f);


  m = new plum(220,230,"plum.gif",10,.99f,.5f);
  boxes = new gift[BOXCOUNT];
  for(int i = 0; i < BOXCOUNT; i++){

    boxes[i] = new gift((int)random(width),(int)random(height),(int)random(20)+20,(int)random(20)+20,10,.80f,.5f);
  }
 
}

int c;

HashSet currentKeys = new HashSet();

public void 	keyPressed(KeyEvent e){
  currentKeys.add(new Integer(e.getKeyCode()));

  println(e.getKeyCode());
  if(e.getKeyCode() == 32){
    if(gameover){
        noLoop();
       gameover = false; 
       startgame();
       loop();
    }
    
    m.jump();
  }

}
public void 	keyReleased(KeyEvent e){
  currentKeys.remove(new Integer(e.getKeyCode()));
}
public boolean isKeyDown(int c){
  return currentKeys.contains(new Integer(c));
}
gift heldBox = null;
float heldXoff,heldYoff;
public void mousePressed(){
  for(int i = 0; i < BOXCOUNT; i++){
    gift thisbox = boxes[i];
    if(thisbox.x <= mouseX && mouseX <= thisbox.x + thisbox.w){
      if(thisbox.y <= mouseY && mouseY <= thisbox.y + thisbox.h){
        heldBox = thisbox;
        heldXoff = thisbox.x - mouseX;
        heldYoff = thisbox.y - mouseY;
        return;
      }
    }
  }
}


public void mouseReleased(){
  heldBox = null;
}
public void mouseDragged(){
  if(heldBox != null){
    float newx =  heldXoff + mouseX; 
    float newy = heldBox.y = heldYoff + mouseY;        
    heldBox.xs = 2*(newx - heldBox.x);
    heldBox.ys = 2*(newy - heldBox.y);
    heldBox.x = newx;
    heldBox.y = newy;

  }

}

boolean mGoLeft = false;


public void draw(){
  
  

  if(random(10)< 1){
    m.jump(); 
  }
  if(random(100)< 1){
    mGoLeft = !mGoLeft;
    m.xs *= -1;
  }


  if(mGoLeft){
    m.xs -= .3f; 
  } 
  else {
    m.xs += .3f; 
  }
  //gravity  
  m.ys += .2f;
  for(int i = 0; i < BOXCOUNT; i++){
    boxes[i].ys += 1;
  }

  m.move();
  for(int i = 0; i < BOXCOUNT; i++){
    boxes[i].move();
  }  
  m.bounds();
  for(int i = 0; i < BOXCOUNT; i++){
    boxes[i].bounds(true);
  }  

  c++;
  if(c % 50 == 0){
    //      m.changeframe(m.currentframe==0?1:0); 
  }

  for(int i = 0; i < BOXCOUNT; i++){

    if(m.overlap(boxes[i],true)){

      m.collide(boxes[i]);
    }
  }
  //round robin collisions... 
  for(int i = 0; i < BOXCOUNT; i++){
    for(int j = i+1; j < BOXCOUNT; j++){
      if(boxes[i].overlap(boxes[j],true)){
        boxes[i].collide(boxes[j]);
      }
    }  
  }


  for(int i = 0; i < BOXCOUNT; i++){
    boxes[i].bounds(true);
  }  


  background(128);

  if(! gameover){
    fill(0);
    text("help the sugardum fairy",10,30);
    text("get to the star",30,60);
    text("by mouse moving gifts!",30,90);
    text("your time:"+((millis()-timestart)/1000),30,120);
  } else {
    fill(128,0,0);
    text("you win!",10,30);
    fill(0,128,0);
    text("merry christmas!",10,60);
    fill(128,0,0);
    text("your time:"+wintime,10,90);
    fill(0,128,0);
    text("space to play again!",10,120);
    
  }

  for(int i = 0; i < BOXCOUNT; i++){
    boxes[i].draw();
  }
  m.draw();

  for(int i = 0; i < BOXCOUNT; i++){
    boxes[i].drawBow();
  }
  star.draw();

  if(star.overlap(m)){
      gameover = true;
      wintime = ((millis()-timestart)/1000);
  }

}
//------------------------------------------

class movesprat extends sprat {
  float xs, ys;
  float mass,friction, rebound;
  //pmass = mass, pfriction is multipler to speed per frame, rebound is multiplier of speed on wall/floor collision
  movesprat(int px,int py, String imgname, float pmass, float pfriction, float prebound){
    super(px,py,imgname);
    friction = pfriction;
    mass = pmass;
    rebound = prebound;
  }
  movesprat(int px,int py, String[] imgname, float pmass, float pfriction, float prebound){
    super(px,py,imgname);
    friction = pfriction;
    mass = pmass;         
    rebound = prebound;

  }

  public void collide(movesprat o){
    float temp;
    temp = o.xs; 
    o.xs =  xs;
    xs = temp;
    temp = o.ys; 
    o.ys =  ys;
    ys = temp;

    nonoverlap(o);




  }


  public void    nonoverlap(movesprat o){
    //figure out which overlap is less, and make that the point where they push out       
    float hlap = spratOverlapHoriz(o).magnitude();
    float vlap = spratOverlapVert(o).magnitude();
    if(hlap < vlap){
      if(x < o.x){
        x -= hlap / 2.0f; 
        o.x += hlap / 2.0f; 
      } 
      else {
        x += hlap / 2.0f; 
        o.x -= hlap / 2.0f;             
      }
    } 
    else {
      if(y < o.y){
        if(o.y + o.h >= height){
          o.y = height - o.h;
          y = o.y - h; 
        } 
        else {
          y -= hlap / 2.0f; 
          o.y += hlap / 2.0f; 
        }
      } 
      else {
        if(y + h >= height){
          y = height - h;
          o.y = y - o.h; 
        } 
        else {
          y += hlap / 2.0f; 
          o.y -= hlap / 2.0f;             
        }
      }

    }

  }

  public void  move(){
    xs *= friction;
    ys *= friction;
    x += xs;
    y += ys; 
  }
  public void bounds(boolean b){
    bounds(); 
  }
  public void bounds(){
    if(x < 0) {
      x = 0;
      xs = abs(xs) * rebound;
    } 
    if(x+w > width) {
      x = width-w;
      xs = abs(xs) * -rebound;
    } 
    if(y < 0) {
      y = 0;
      ys = abs(ys) * rebound;

    } 
    if(y+h > height) {
      // print("ys is "+ys);
      y = height-h;
      ys = abs(ys) * -rebound;
    } 


  }



}



class sprat{
  float x,y;
  int 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);
  } 

  public 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);
  } 
  public void changeframe(int whatframe){
    currentframe = whatframe;
    w = img[currentframe].width;
    h = img[currentframe].height;
  }

  public 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
  public int pixelAtPhysicalLocation(int px, int py){
    int rx = px - PApplet.parseInt(x);
    int ry = py - PApplet.parseInt(y);
    return img[currentframe].pixels[rx + (ry * w)];
  }
  public boolean overlap(sprat other){
    return overlap(other, false);
  }

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

    //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...
  public 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);
  }

  public 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; 
  }
  public int magnitude(){
    return abs(max-min) ;
  }

}

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 gift extends movesprat {
  int color1,color2;
  gift(int px,int py, int pw, int ph, float pmass, float pfriction, float prebound){
    super(px,py,"lin.gif",pmass,pfriction,prebound);
    x = px;
    y = py;
    w = pw;
    h = ph;
    friction = pfriction;
    mass = pmass;         
    rebound = prebound;
    color1 = color(random(255),random(255),random(255));
    color2 = color(random(255),random(255),random(255));
  }


  public void draw(){
    noStroke();    
    fill(color1);
    rect(x,y,w,h);
    fill(color2);
    rect(x+(w*3/8),y,w/4,h);
    rect(x,y+(h*3/8),w,h/4);


  }

  public void drawBow(){
    noStroke();    
    fill(color2);
    float r = w / 4;
    ellipse(x+(w/2),y-(r*.5f),r,r);

  }

}





class plum extends movesprat{

  public void collide(movesprat o){

    nonoverlap(o);




  }


  plum(int px,int py, String imgname, float pmass, float pfriction, float prebound){
    super(px,py,  imgname,  pmass,  pfriction,  prebound); 
  }
  public void jump(){

    //if on floor jump
    if(y+h >= height -2){
      ys = 15;
    }

    for(int i = 0; i < BOXCOUNT; i++){
      if(  spratOverlapHoriz(boxes[i]) != null){
        if(y+h >= boxes[i].y - 20){
          ys = 15; 
        }
      }

    }

  }

}

  static public void main(String args[]) {     PApplet.main(new String[] { "sugardum" });  }}