ArrayList invaders = new ArrayList();
ArrayList  bullets = new ArrayList (); 
Gunner g = new Gunner();
int level = 1;
int score = -1;
int highscore = 50;
boolean playing = false;
void setup(){
  frameRate(30);
  
   size(500,500); 
noCursor();
textAlign(CENTER,CENTER);
textFont(loadFont("courier"));
}
void startGame(){
  score = 0;
  level = 1; 
 invaders = new ArrayList();
 bullets = new ArrayList(); 
  addInvaders(); 
  playing = true;
}
void mouseReleased(){
  if(!playing) startGame();
}
void addInvaders(){
   for(int i = 0; i< level *5;i++){
     invaders.add(new Invader());
   }
}
void draw(){
  background(100);
text("highscore:"+highscore,0,0,500,50);
if(!playing){
  fill(200);
  String txt = "manyinvaders\n\n";
  if(score != -1) txt += "last score:"+score;
  txt += "\n\nclick to play";
 text(txt,0,0,500,500); 
} else{
  text("score:"+score,0,450,100,50);
  text("level:"+level,400,450,100,50);
}
  int invadersToAdd = 0;
  ArrayList bulletsToKill = new ArrayList();
  ArrayList invadersToKill = new ArrayList();
  
  if(playing && frameCount % 2 == 0){
   bullets.add(new Bullet()); 
  }
  
  
  for(Invader i : invaders){
    i.move();
    if(i.tooLow()) invadersToKill.add(i);
    
    if(overlapBox(i,g)){
       playing = false; 
       g.ys = 0;
    }
    
     i.draw(); 
  }
  
  for(Bullet  b : bullets){
      b.move();
      if(b.tooHigh()){
         bulletsToKill.add(b); 
      }
      
  for(Invader i : invaders){
     if(overlapBox(b,i)){
       if(i.alive){
         score++;
         if(score > highscore) highscore = score;
          i.alive = false; 
          invadersToAdd++;
       }
       i.hitByBullet();
       bulletsToKill.add(b); 
     }
      
  }
     b.draw(); 
  }
  g.move();
  g.draw();
  
removeAll(bullets,bulletsToKill);
removeAll(invaders,invadersToKill);  
  if(playing && invaders.size() <= 0){
     level++;
      addInvaders(); 
  }
}
void removeAll(ArrayList big, ArrayList bad){
    for(Object b : bad){
        big.remove(b);
        }
}
  float IMOVE = .1;
class Invader extends boxish{
   float xs,ys;
  float cx,cy;
  boolean alive = true;
  Invader(){
    w = random(5,20);
    h = random(5,20);
    cx = random(0,500);
    cy = random(100,400);
    x = random(0,500);
    y = random(-h,-h-20);
    xs = random(-IMOVE*60,IMOVE*60);
    ys = random(-IMOVE*60,IMOVE*60);
  /*  c = color(
      random(128,255),
      random(128,255),
      random(128,255)
    );*/
    c = color(255,128,0);
  }
void hitByBullet(){
  ys -= IMOVE* map(w*h,25,400,60,10);
}
boolean tooLow(){
 return y > 500; 
}
  void move(){
    if(alive){
    if(x < cx) xs += IMOVE; 
    else xs -= IMOVE;
    if(y < cy) ys += IMOVE; 
    else ys -= IMOVE;
    } else ys += IMOVE;
    
    
    if(x < 0) {
        x = 0; xs = abs(xs);
    } 
    if(x > 500-w) {
        x = 500-w; xs = -abs(xs);
    } 
    
    if(y < 0) {
        y = 0; ys = abs(ys);
    } 
    if(alive && y > 500-h) {
        y = 500-h; ys = -abs(ys);
    } 
    
    
    
    x += xs;
    y += ys;
  }
  
  void draw(){
  if(! alive){
  
    c = color(128,64,0);
  }  
    stroke(c);
      strokeWeight(2);
        fill(c);
        rect(x,y,w,h);    
        int dir;
        if(alive) {        
          line(x,y+h,x-w*.5,y+h*1.5);
          line(x+w,y+h,x+w*1.5,y+h*1.5);
        } else {
          line(x,y,x-w*.5,y-h*.5);
          line(x+w,y,x+w*1.5,y-h*.5);
          
        }
    }
  
  
}
class Gunner extends boxish{
  Gunner(){
    super();
    w = 40;
    h = 20;
   c = color(200);
  }
  float ys;
  void move(){
if(playing || score == -1){   
   y =constrain(mouseY, 300,500-h);
  x = constrain(mouseX,0,500-w); 
  c = color(200);
} else {
   y += ys; 
   ys += .1;
   c = color(40);
}
  }
}
float BULSPEED = 8;
class Bullet extends boxish{
    Bullet(){
       super();
        w = 10;
       h = 10;
       x = g.x + g.w / 2 - w / 2;
      y = g.y;
    }
    void move(){
       c = color(random(150,250));
       y -= BULSPEED;
       
    }
    boolean tooHigh(){
       return y < -h; 
    }
    
}  
void mousePressed(){
   bullets.add(new Bullet()); 
}
class boxish{
    float w,h,x,y;
    color c;
    
    boxish(){
 
    }
    
    void draw(){
      noStroke();
        fill(c);
        rect(x,y,w,h);        
    }    
}
boolean overlapBox(boxish b1, boxish b2){
    if(overlapHoriz(b1,b2) && overlapVert(b1,b2)){
        return true;
    } else {
        return false;    
    }
}
boolean overlapHoriz(boxish b1, boxish b2){
    float b1left = b1.x;
    float b1right = b1.x+b1.w;
    float b2left = b2.x;
    float b2right = b2.x+b2.w;
    if(b1left < b2left && b1right < b2left) return false;
    if(b1left > b2right && b1right > b2right)return false;
    return true;
}
boolean overlapVert(boxish b1, boxish b2){
    float b1top = b1.y;
    float b1bot = b1.y+b1.h;
    float b2top = b2.y;
    float b2bot = b2.y+b2.h;
    if(b1top < b2top && b1bot < b2top) return false;
    if(b1top > b2bot && b1bot > b2bot) return false;
    return true;
}