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 bouncers8 extends BApplet {
// Set the font and its size (in units of pixels) 

int xWidth = 800, yHeight = 400;

int total = 1000;
Bouncer[] bouncer =  new Bouncer[total];

boolean clear = true;
boolean click = false;

int counter = 0;
int strokeVar = 2;

void setup() {

  size(800,400);
  noBackground();
  noStroke();
  fill(85);
  rect(0,0,width,height);

  for (int i=0; i<total; i++){
    bouncer[i] = new Bouncer(width/2, height/2 + random(-5,5), random(-75,75), random(-2,2), random(-2,2));
  }
}
 
void loop() {
  drawState();
  if(keyPressed) { 
    if (key == '1') { 
      strokeVar = 1;
    } else if (key == '2') {
      strokeVar = 2;
    } else if (key == '3') {
      strokeVar = 3;
    } else if (key == '4') {
      strokeVar = 4;
    } else if (key == '5') {
      strokeVar = 5;
    }
  }
  
  if (mousePressed){
    click = true;
  }
  
  for (int i=0; i<total; i++){
    bouncer[i].bounce();
  }
} 

void mouseReleased () {
  click = false;
}

void drawState(){
  if (clear){
    noStroke();
    fill(85);
    rect(0,0,width,height);
  }
}

void keyReleased () {
  if (key == ' ' && clear) { 
    clear = false;
  } else if (key == ' ' && !clear) {
    clear = true;
  }
}

class Bouncer {
  float xPos;
  float yPos;
  float xOld = mouseX;
  float yOld = mouseY;
  float x2Old = mouseX;
  float y2Old = mouseY;
  float left = 0;
  float right = width;
  float floor = height/2 + random(-2,2);
  float ceiling = 0;
  float friction = random(0.3f,0.7f);
  float elastic = random(0.3f,0.7f);
  float gravity;
  float rot;
  float xd, yd;
  float xVel, newXVel;
  float yVel, newYVel;
  float xDelta, yDelta, distance;
  Bouncer (float xp, float yp, float rp, float xv, float yv) {
    xPos = xp;
    yPos = yp;
    rot = rp;
    xVel = xv;
    yVel = yv;
  }

  void bounce () {
    x2Old = xOld;
    y2Old = yOld;
    xOld = xPos;
    yOld = yPos;
    
    if (yPos > floor){
      gravity = -1;
    } else {
      gravity = 1;
    }
    
    yVel = yVel + (gravity * elastic);
    xPos = xPos + xVel;
    yPos = yPos + yVel;

      if (xPos > right){
        xPos = right;
        xVel = xVel * -elastic;
      } else if (xPos < left){
        xPos = left;
        xVel = xVel * -elastic;
      }
    if (!click){
      if (gravity == 1){
        if (yPos > floor){
          yVel = yVel * elastic;
          xVel = xVel * friction;
          gravity = -1;
        }
      } else {
        if (yPos < floor){
          yVel = yVel * elastic;
          xVel = xVel * friction;
          gravity = 1;
        }
      }
    }
    
    xDelta = mouseX - xPos;
    yDelta = mouseY - yPos;
    distance = sqrt(sq(xDelta) + sq(yDelta));
    
    if (!click && distance < 50){
      //gravity = gravity * -1;
      if (mouseX > pmouseX){
        xd = mouseX - pmouseX;
        if (xd > 20){
          xd = 20;
        }
        xVel = random(0,xd);
      } else if (pmouseX > mouseX){
        xd = mouseX - pmouseX;
        if (xd < -20){
          xd = -20;
        }
        xVel = random(xd,0);
      } else {
        xVel = random(-5,5);
      }
      
      if (mouseY > pmouseY){
        yd = mouseY - pmouseY;
        if (yd > 20){
          yd = 20;
        }
        yVel = random(0,yd);
      } else if (pmouseY > mouseY){
        yd = mouseY - pmouseY;
        if (yd < -20){
          yd = -20;
        }
        yVel = random(yd,0);
      } else {
        yVel = random(-5,5);
      }
      
    } else if (click && distance < 250){
      newXVel = xVel * elastic + (mouseX - xPos) * friction;
      newYVel = yVel * elastic + (mouseY - yPos) * friction;
      xVel = xVel - ((xVel - newXVel) * .05f);
      yVel = yVel - ((yVel - newYVel) * .05f);
    }
    

    strokeWidth(strokeVar);
    stroke((abs(yVel) + abs(xVel))*2);
    line(xPos, yPos, xOld, yOld);
    strokeWidth(strokeVar/2);
    stroke((abs(yVel) + abs(xVel))*4,0,0);
    line(xPos, yPos, xOld, yOld);
    strokeWidth(strokeVar/4);
    stroke((abs(yVel) + abs(xVel))*16,0,0);
    line(xOld, yOld, x2Old, y2Old);
  }
}


}