ArrayList troopers = new ArrayList();
ArrayList bullets = new ArrayList();
ArrayList copters = new ArrayList();

Gun g = new Gun();
void setup(){
  size(500,500); 
  strokeWeight(3); 
  stroke(0); //smooth();
}

float copChance = 2;

void draw(){
  Iterator i;
  /*
  if(random(100) < 20){
   troopers.add(new Trooper(random(0,500),random(0,250))); 
   }*/

  background(200,200,255); 


  if(random(100) < copChance){
    copters.add(new Copter()); 
  }



  i = copters.iterator();
  while(i.hasNext()){
    Copter c = (Copter) i.next();
    c.move();
    c.draw();
  }



  i = troopers.iterator();
  while(i.hasNext()){
    Trooper t  = (Trooper) i.next();
    if(t.move()) i.remove();
    t.draw(); 
  }


  i = bullets.iterator();
  while(i.hasNext()){
    boolean killBullet = false; 
    Bullet b  = (Bullet) i.next();
    if(b.move()){
      killBullet = true; 
    }

    Iterator it = troopers.iterator();
    while(it.hasNext()){
      Trooper t = (Trooper) it.next();
      if(t.hit(b)){
        it.remove();
        killBullet = true;  
      } 

    }

    Iterator ic = copters.iterator();
    while(ic.hasNext()){
      Copter c = (Copter) ic.next();
      if(c.hit(b)){
        killBullet = true;  
      } 
    }


    if(!killBullet){
      b.draw(); 
    } 
    else {
      i.remove(); 
    }
  }


  i = troopers.iterator();
  while(i.hasNext()){
    boolean troopKill = false;
    Trooper t = (Trooper)i.next();
    Iterator ic = copters.iterator();
    while(ic.hasNext()){
      Copter c = (Copter)ic.next();
      if(c.isDead && c.bam(t)){
        troopKill = true;
      } 
    }

    Iterator i2 = troopers.iterator();
    while(i2.hasNext()){
      Trooper t2 = (Trooper) i2.next();
      if(t != t2){
        if(t.isLanded && ! t2.isLanded && ! t2.hasChute && overlap(t.x,t.y,TROOPERWIDTH,TROOPERHEIGHT,
        t2.x,t2.y, TROOPERWIDTH,TROOPERHEIGHT)){
          troopKill = true;                                                               
        }
      }
    }     



    if(troopKill || t.y > 500){
      i.remove(); 
    }

  }

  Iterator ic = copters.iterator();
  while(ic.hasNext()){
    Copter c = (Copter)ic.next();
    if(! c.isDead){
      if(random(100) < 2){
        troopers.add(new Trooper(c.x,c.y));
      } 
    }




    if(c.y > 500 || (c.left && c.x < -100) || (!c.left && c.x > 600)){
      ic.remove() ;
    }
  }


  g.draw();

}


class Copter{
  float  x,y;
  boolean left = false;

  boolean bam(Trooper t){
    if(overlap(t.x,t.y,TROOPERWIDTH,TROOPERHEIGHT, x-30,y,60,15)){
      return true;
    } 
    return false;
  }

  Copter(){
    if(random(100) < 50){
      left = true;
      x = 550; 
    } 
    else {
      x = -50; 

    }
    y = random(10,200);
  }
  boolean hit(Bullet b){
    int flip = 1;
    if(left){
      flip = -1;
    } 

    if(

    (     between(b.x,x,x+(flip*30)) &&   between(b.y,y,y+20)     )
      || (between(b.x,x,x-(flip*30)) && between(b.y,y,y+10))
      ){
      isDead = true;
      return true; 
    }
    return false;

  }
  boolean between(float val, float a, float b){
    float low  = a; 
    float high = b;
    if(low > high){
      low = b; 
      high = a; 
    }
    if(val >= low && val <= high){
      return true;
    } 
    else {
      return false; 
    }
  }
  float ys = 0;
  void move(){
    if(left){
      x -= 2;
    } 
    else {
      x += 2; 
    } 
    if(isDead){
      ys += .03;
    }
    y += ys;
  }

  float blade = 20;
  float bladedir = 6;
  boolean isDead;
  void draw(){
    //println(troopers.size()+" "+copters.size()+" "+bullets.size());
    fill(0,0,200);
    if(isDead) fill(0);
    int flip = 1;
    if(left){
      flip = -1;
    } 
    rect(x,y,(flip* 30),20);
    rect(x,y,-(flip* 30),10);

    line(x+(15*flip)-blade, y -5, x+(15*flip)+blade,y-5);
    if(isDead) return;
    blade += bladedir;
    if(blade < 0) {
      bladedir = 6; 
    }
    if(blade > 30) {
      bladedir = -6; 
    }
  }

}


float TROOPERWIDTH = 5;
float TROOPERHEIGHT = 10;

class Trooper {
  boolean hasChute = true;
  boolean isDead = false;
  boolean isLanded = false;
  float x,y, ys = .8, xs = 0;
  Trooper(float sx,float sy){
    x = sx;
    y = sy;
  }  




  boolean hit(Bullet b){
    if(hasChute){
      if(b.x >= x - TROOPERHEIGHT &&    b.x <= x + TROOPERHEIGHT+TROOPERWIDTH && b.y >=  y - TROOPERHEIGHT && b.y <=  y - TROOPERHEIGHT+TROOPERWIDTH){
        hasChute = false;
      }
    }

    if(b.x >= x &&      b.x <= x+TROOPERWIDTH && b.y >= y && b.y <= y+TROOPERHEIGHT){
      isDead = true;
      hasChute = false;
      return true;
    } 
    return false;
  }

  boolean move(){
    if(! isLanded && y > 500 - TROOPERHEIGHT){
      y = 500 - TROOPERHEIGHT;
      if(!hasChute){
        return true; 
      }
      hasChute = false;
      isLanded = true; 
    }
    if(isLanded){
      if( abs(250-  x + TROOPERWIDTH / 2 ) < 5){
//         println("bang"); 
      } else {
         if(x > 250) x -= .3; 
         if(x < 250) x += .3; 
      }
    } 
    else {
      if(!hasChute){
        ys += .03;
      }
      y += ys;  
      x += xs;
    }  
      return false;  

  }
  void draw(){
    if(hasChute){
      fill(128);
      rect(x - TROOPERHEIGHT, y - TROOPERHEIGHT, TROOPERHEIGHT*2 + TROOPERWIDTH,TROOPERWIDTH);
      line(x - TROOPERHEIGHT,y - TROOPERHEIGHT+TROOPERWIDTH,x,y);
      line(x + TROOPERHEIGHT+TROOPERWIDTH,y - TROOPERHEIGHT+TROOPERWIDTH,x+TROOPERWIDTH,y);
    } 
    if(isDead) fill(0);
    else if(isLanded) fill(200,50,50);
    else fill(50,100,50);
    rect(x,y,TROOPERWIDTH,TROOPERHEIGHT); 
  }


}
boolean leftPressed, rightPressed, shiftPressed;
void keyPressed(){
  if(keyCode == LEFT){
    leftPressed = true;
  } 
  if(keyCode == RIGHT){
    rightPressed = true;
  } 
  if(key == 'z'){
    shiftPressed = true; 
  }
}
void keyReleased(){
  if(keyCode == LEFT){
    leftPressed = false;
  } 
  if(keyCode == RIGHT){
    rightPressed = false;
  } 
  if(key=='z'){
    shiftPressed = false; 
  }

}


class Gun{
  float angle = -PI/2;
  float x = 250, y = 480; 
  void draw(){
    fill(128);
    pushMatrix();
    translate(x,y);
    rect(-10,0,20,40);
    rotate(angle);
    rect(0,-5,30,10);
    ellipse(0,0,20,20);
    popMatrix();
    //angle += .1;
    if(leftPressed && angle >= -PI){
      angle-=.1;

    }  
    if(rightPressed && angle <= 0){
      angle+= .1; 
    }  
    checkFire();
  } 

  void checkFire(){
    if(shiftPressed && frameCount % 3 ==0){
      bullets.add(new Bullet(x,y,angle));
    } 
  }

}

float BULLETSPEED = 3;
class Bullet{
  float x,y,a;
  Bullet (float sx, float sy, float sa){
    x = 250 + cos(sa)*30 ; 
    y = 480 +sin(sa)*30;
    a =sa; 
  }
  boolean move(){
    x += cos(a)*BULLETSPEED;
    y += sin(a)*BULLETSPEED;
    if(x < 0 || x > 500 || y < 0 || y > 500){
      return true; 
    }
    return false;
  }
  void draw(){
    rect(x,y,1,1); 
  }
}







boolean overlap(float x1,float y1, float w1,float h1, float x2, float y2, float w2, float h2){
  if(  overlapline(x1,x1+w1,x2,x2+w2) && overlapline(y1,y1+h1,y2,y2+h2)  ){
    return true;
  }
  return false;

}


boolean overlapline(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;
}