int RED = 0;
int BLACK = 1;

float GROUND = 500;
HashSet ants = new HashSet();
HashSet bullets = new HashSet();
Ant player;

void setup(){
  size(1000,600);
  frameRate(40);
  player = new Ant(RED,200,100);
  ants.add(player);
  textFont(loadFont("Arial-Black-10.vlw"));
}
void draw(){

  background(128,128,200);
  noStroke();
  fill(139,69,19);
  if(random(10) < 1){
    ants.add(new Ant(BLACK,width+20,GROUND-50)) ;
  }
  if(random(10) < 1){
    ants.add(new Ant(RED,-20,GROUND-50)) ;
  }

  rect(0,GROUND,width,height-GROUND);
  Iterator antit = ants.iterator();
  while(antit.hasNext()){
    Ant a = (Ant)antit.next(); 
    if(!a.move()){
      antit.remove();
    }
    a.draw();
  }
  Iterator bullit = bullets.iterator();
  while(bullit.hasNext()){
    boolean bulletgone = false;
    Bullet b = (Bullet)bullit.next(); 
    if(! b.move()){
      bullit.remove(); 
      bulletgone = true;
    }

    antit = ants.iterator();
    while(antit.hasNext()){
      Ant a = (Ant)antit.next(); 
      if(a.hitBy(b) ){
        a.die();
        if(!bulletgone) {
          bullit.remove();
          bulletgone = true; 
        }
      }
    }     

    b.draw();




  }

  if(respawn){

    player = new Ant(RED,random(50,450),100);
    ants.add(player);
    respawn = false;
  }
  player.drawYou();  
}


boolean respawn = false;
HashSet keysPressed = new HashSet();

void keyPressed(){
  //  print("up "+keyCode);
  keysPressed.add(keyCode);
  if(key == 'k') {
    player.die(); 
  }
}
void keyReleased(){
  //print("down "+keyCode);

  keysPressed.remove(keyCode);

}


class Bullet{
  int dir; 
  float x,y;
  Bullet (float x, float y, int dir){
    this.x = x;
    this.y = y;
    this.dir = dir; 
  }
  boolean move(){
    x = x + (dir * 3);
    if(x < -10) return false;
    if(x > width+10) return false;
    return true;
  }
  void draw(){
    strokeWeight(2);
    stroke(0);
    fill(0);
    rect(x,y,1,1);
  }
}

class Ant {
  float x,y;
  int whatarmy;
  color mycolor;
  int dir;
  boolean isOnCorpse = false;
  float REALHEIGHT;
  Ant(int whatarmy,float  x,float y){
    this.whatarmy = whatarmy;
    this.x = x;
    this.y = y; 
    if(whatarmy == RED){
      mycolor = color(128,0,0); 
      dir = 1;
    } 
    else {
      mycolor = color(64,64,64); 
      dir = -1;
    }
    REALHEIGHT = H*1.2;
  }
  float ys;
  float GRAV = .4;
  int gunrecharge = 0;
  boolean move(){



    gunrecharge++;
    if(gunrecharge >= 100){
      gunrecharge = 100;  
    }



    if(this==player&& keysPressed.contains(90)){
      jump(); 
    }
    // println(keyCode);
    if(this==player&& keysPressed.contains(37)){

      dir = -1;
      x = x -1.5;
    }
    if(this==player&& keysPressed.contains(39)){
      dir = 1;
      x = x +1.5;
    }

    if(this == player && keysPressed.contains(88)){
      shoot();
    }
    if(this != player && alive){
      x =x + dir * 1.5;
      if(random(10) < 1){
        jump(); 
      }
      if(random(30) < 1){
        shoot();
      }


    }


    isOnCorpse = false;
    ys += GRAV;
    y = y + ys;

    if(y + H*1.2 >= GROUND){
      y = GROUND - REALHEIGHT;
      ys = 0; 
    } 
    else{
      if(!alive || ys > 0.1){

        Ant deadoverlapper = overlapsDeadAnt();
        if(deadoverlapper != null){
          y = deadoverlapper.y - REALHEIGHT;
          isOnCorpse = true;
          ys = 0;
        }
      }

    }



    if(this != player){
      if(dir < 0){
        if(x < -100){
          return false;
        }  
        else {
          if(x > width+100){
            return false;
          }           
        }

      }

    }

    return true;    
  }


  Ant overlapsDeadAnt(){
    Iterator antit = ants.iterator();
    while(antit.hasNext()){
      Ant a = (Ant)antit.next(); 
      if((!a.alive) && a != this && overlap(this,a)){
        return a;
      }    
    }
    return null;
  }

  boolean alive = true;
  float DIEHEIGHT;
  void die(){
    if(! alive) return;

    DIEHEIGHT = y + H*.7;

    float tempW = W;
    W = H;
    H = tempW;

    y += W;
    ys = 0;
    REALHEIGHT = H;
    if(this == player){
      respawn = true;
    }
    alive = false;
  }

  boolean hitBy(Bullet b){
    if(b.x > x && b.x < x+W && b.y > y && b.y < y+H){
      return true; 
    } 
    return false;
  }

  float W = 10    ;
  float H = 20;

  void draw(){
    fill(mycolor);
    strokeWeight(2);
    stroke(0);
    pushMatrix();
    translate(x,y);
    if(alive){
      rect(0,0,W,H);
      line(0,H*.4,-W*.5,H*.75);
      line(0,H*.7,-W*.5,H);
      line(0,H,-W*.5,H*1.2);

      line(W,H*.4,W*1.5,H*.75);
      line(W,H*.7,W*1.5,H);
      line(W,H,W*1.5,H*1.2);

      fill(128);

      rect((-W*.25) + (dir*(GUNW/2)),H*.5, (W*1.5),H*.2) ;


    } 
    else { //not alive
      rect(0,0,W,H);
    }
    popMatrix();
  }
  float GUNW = W*1.5;
  void shoot(){
    if(gunrecharge > 0){
      bullets.add(new Bullet(x+ (dir*(GUNW)),y+H*.5,dir)); 
      gunrecharge = -20;
    }
  }

  void drawYou(){
    fill(color(255));
    text("YOU",x-W/2,y+H*1.75);
  }

  void jump(){
    if(    (y == (GROUND - H*1.2)) || isOnCorpse){
      ys = - 6; 
    } 

  }




}


boolean overlap(Ant a1,Ant a2){
  if(  overlap(a1.x,a1.x+a1.REALHEIGHT,a2.x,a2.x+a2.W)
    && overlap(a1.y,a1.y+a1.H,a2.y,a2.y+a2.H) ){
    return true;
  }
  return false;

}


boolean overlap(float line1val1,float line1val2,float line2val1,float line2val2){
  float line1min = min(line1val1,line1val2);
  float line1max = max(line1val1,line1val2);
  float line2min = min(line2val1,line2val2);
  float line2max = max(line2val1,line2val2);

  if(line1min < line2min && line1max < line2min){
    return false; 
  }
  if(line1min > line2max && line1max > line2max){
    return false; 
  }  


  return true;
}