Circle player;
ArrayList<Circle> circles;
float targx, targy;
int level = 1;
float alpha;
boolean win = false, go;
void setup() {
  size(800, 600);
  generate();
}
void draw() {
  strokeWeight(2);
  if (!player.dead) {
    int co = -1, sd = 0;
    for (Circle ci:circles) {
      co++;
      if (ci.dead) {
        sd++;
      }
    }
    if (sd==co)win=true;
  }
  if (frameCount%80==0) {
    int v=0, b=0;
    for (Circle ci:circles) {
      if (ci.dead==false) {
        v++;
        if (ci.size>player.size)b++;
      }
    }
    if (b==v-1) {
      if (!player.dead&&win==false) {
        Circle cr = new Circle("enemy", circles.size());
        if (random(0, 9)>5)cr.size=player.size/1.2;
        else cr.size=player.size*1.2;
        cr.help=true;
        circles.add(cr);
      }
    }
  }
  if (player.dead||win&&alpha>0)alpha--;
  if (alpha<=0) {
    if (win)level++;
    else if (level>1)level=1;
    win=false; 
    generate();
  }
  if (player.dead)fill(255, 30);
  else fill(255, player.size+20);
  rect(-1000, -1000, 2000, 2000);
  pushMatrix();
  translate(width/2-player.pos.x, height/2-player.pos.y);
  fill(0, 0);
  stroke(0, alpha);
  rect(-100, -100, width+200, height+200);
  for (int i=0;i<circles.size();i++) {
    Circle circle = circles.get(i);
    if (!circle.dead)circle.display(i);
    else { 
      circles.remove(i);
      i--;
    }
  }
  popMatrix();
  
  textAlign(CENTER);
  textSize(50);
  fill(20, 150-player.delpha);
  text("Level "+level, width/2, height/2);
  if(frameCount<360){
  fill(180,177,177, 150-player.delpha);
  
  textSize(20);
  text("Circumvent by Ewen Wang", width/2, height-20);
  
  }
}
void generate() {
  go=false;
  targx=0;
  alpha= 160;
  circles = new ArrayList<Circle>();
  player = new Circle("player", 0);
  circles.add(player);
  for (int i=1;i<level*2;i++) {
    //Circle circle = circles.get(i);
    Circle circle = new Circle("enemy", i);
    circles.add(circle);
    circle.size=sqrt(i)*40+30;
  }
}
class Circle {
  float size=50;
  PVector pos=new PVector(width/2, height/2);
  PVector velocity = new PVector(0, 0);
  color c = color(random(9, 200), random(9, 200), random(9, 200));
  boolean dead = false, help = false;
  float delpha = 1;
  String s;
  Circle(String s, int id) {
    this.s=s;
    if (s=="enemy") {
      float r = random(0, 10), tx, ty;
      if (r<5) {
        tx=random(-100, width+100);
        ty=height+100;
        if (r<=3)ty=-100;
      }
      else {
        ty=random(-100, height+100);
        tx=-100;
        if (r>=7)tx=width+100;
      }
      pos = new PVector(tx, ty);
    }
  }
  void display(int z) {
    if (!dead&&s=="enemy"&&circles.get(0).s!="enemy") {
      int b;
      if (help)b=1;
      else b=z;
      velocity = new PVector(circles.get(b-1).pos.x-pos.x, circles.get(b-1).pos.y-pos.y);
      velocity.normalize();
      velocity.div(sqrt(size)/(level+7));
    }
    if (delpha<alpha)delpha++;
    if (delpha>alpha)delpha--;
    for (int i=0;i<circles.size();i++) {
      Circle cir =circles.get(i);
      float rad = (size+cir.size)/2;
      if (i!=z&&dist(pos.x, pos.y, cir.pos.x, cir.pos.y)<rad) {
        stroke(255, 0, 0, alpha);
        if (size>cir.size)size+=50/size;
        else size-=size/(size-5);
        float tempx = cir.pos.x+random(-10, 10), tempy = cir.pos.y+random(-10, 10);
        strokeWeight(1);
        line(cir.pos.x, cir.pos.y, tempx, tempy);
        line(tempx, tempy, pos.x, pos.y);
      }
    }
    noStroke();
    fill(c, delpha/1.9);
    ellipse(pos.x, pos.y, size, size);
    pos.add(velocity);
    if (pos.x+size/2>width+100) {
      velocity.x/=-2;
      velocity.y/=2;
      pos.x--;
      if (s!="enemy")go=false;
    }
    else if (pos.x-size/2<-100) {
      velocity.x/=-2;
      velocity.y/=2;
      pos.x++;
      if (s!="enemy")go=false;
    }
    else if (pos.y+size/2>height+100) {
      velocity.y/=-2;
      velocity.x/=2;
      pos.y--;
      if (s!="enemy")go=false;
    }
    else if (pos.y-size/2<-100) {
      velocity.y/=-2;
      velocity.x/=2;
      pos.y++;
      if (s!="enemy")go=false;
    }
    else if (s!="enemy"&&go) {
      player.velocity.x=(targx-player.pos.x)/40;
      player.velocity.y=(targy-player.pos.y)/40;
    }
    if (size<=5) {
      dead=true;
      velocity.x=0;
      velocity.y=0;
    }
  }
}
void keyPressed() {
  generate();
}
void mousePressed() {
  targx=mouseX+player.pos.x-width/2;
  targy=mouseY+player.pos.y-height/2;
  go = true;
}