String title=  "Diver and fish (version 3)";
String author=  "B.A.Martin";

Fish fO, f1, f2;;
Diver dl,d2,d3;
int nb, nd, nf, l=1;
float surface=100;

void setup() {
  // setup //
  size( 800, 700 );
  noStroke();
  rectMode(CORNER);
  restart();
}
void restart( ) {
  // Fish
  f0=  new Fish( 0, 20, 150 );                            // DO NOT COPY //
  f1=  new Fish( 0, 20, 200 );                            // DO NOT COPY //
  f2=  new Fish( 0, 20, 250 );                            // DO NOT COPY //
  // Button and diver.
  dl=  new Diver( 50, surface, 255,0,0 );                 // DO NOT COPY //
  d2=  new Diver( 150, surface, 155,255,0 );              // DO NOT COPY //
  d3=  new Diver( 250, surface, 0,255,255 );              // DO NOT COPY //
}
void keyPressed() {
  // Key handler //
  if (key=='q') exit();
  if (key=='r') restart();
  if (key=='1') dl.dive();      // Start diving.
  if (key=='2') d2.dive();      // Start diving.
  if (key=='3') d3.dive();      // Start diving.
}

void draw() {
  // Next frame:  Fish swim back and forth.  Divers dive slowly, when button is clicked.
  scene();
  action();
  show();
  // Text.
  fill(0);
  text( title, width/3, 30 );
  text( author, 20, 680 );
  text( "Press 1, 2, or 3 key to dive for fish.  (r to restart; q to quit)", width/3, height-20 );
}
void scene() {
  // Sky & sea.
  background( 150,200,255 );
  // Sea
  fill( 50,150,100 );
  rectMode(CORNER);
  rect( 0,100, width,height );
}
void show() {
  // Show everything:  fish, boat AND/OR diver.
  dl.show();
  d2.show();
  d3.show();
  //
  f0.show();
  f1.show();
  f2.show();
}
void action() {
  // Move everything:  fish, boat OR diver.
  dl.move();
  d2.move();
  d3.move();
  //
  f0.move();
  f1.move();
  f2.move();
  // Check for divers netting fish
  dl.net( f0 );  dl.net( f1 );  dl.net( f2 );
  d2.net( f0 );  d2.net( f1 );  d2.net( f2 );
  d3.net( f0 );  d3.net( f1 );  d3.net( f2 );
}

class Fish {
  //// Fish:  swims right until width.  Then new fish appears with random speed.
  float x,y, dx=2, dy=0;
  float w=30,h=20;
  int r,g,b;
  int n;
  // CONSTRUCTORS //
  Fish( int n, float x, float y ) {
    this.x=  x;
    this.y=  y;
    this.n=  n;
    this.dx=  random(0.25,2.5);
    randomcolor();
  }
  void randomcolor() {                            // DO NOT COPY //
    r=  int( random(50,255) );    g=  int( random(50,150) );    b=  int( random(50,200) );
  }
  // METHODS:  move & show
  void move() {
    x += dx;    y += dy;                            // DO NOT COPY //
    if (x>width) { reset(); }
  }
  void reset() {
          // New fish.
          x=0;
          dx=  random( 0.25, 3 );
          randomcolor();
  }
  void show() {
    fill(r,g,b);
    ellipse(x,y,w,h);
    triangle( x-w/2+8,y, x-w/2-10,y-10, x-w/2-10, y+10 );
    ellipse( x+w/2-6,y-6, 6,6 );                            // DO NOT COPY //
    fill(255,0,0);                                          // DO NOT COPY //
    ellipse( x+w/2-6,y-6, 3,3 );                            // DO NOT COPY //
  }
}
    
class Diver {
  //// Diver (and boat);
  float x,y, dx=2,dy=0;
  int r,g,b;
  int n=0;
  int caught=0, total=0;
  // CONSTRUCTORS //
  Diver( float x, float y, int r, int g, int b ) {
    this.x=  x;
    this.y=  y;
    this.r=r; this.g=g; this.b=b;
    nd++;
    this.n=  nd;
  }
  // METHODS:  move and show (the diver OR the boat).
  void show() {
    // Draw boat & diver (if diving).
    fill(r,g,b);
    rect( x,surface, 40,-20 );        // Boat
    fill(0);
    text( "#"+n, x+5,surface-5 );            
    text( total, x+20,surface-25 );    // Show total
    fill(r,g,b);
    // Diver
    if (dy>0) {
          triangle(x,y, x-30,y+20, x+30,y+20 );       // Diver diving with open net.
          text( caught, x+20,y-10 );                  // How many fish caught (on this dive).
    }
   if (dy<0) {
          ellipse( x,y, 25,35 );                          // Diver ascending (with closed net).
    }
  }
  void move() {
    // Move boat/diver.
    if (dy==0) {
      // Boat is moving.  (Diver is not diving.)
      if (x<50) dx=  -dx;
      if (x>width-50) dx=  -dx;
      x += dx;
    } else {
        // Diver is still diving.
        y += dy;
        if (y>height-20) dy=  -3;    // Begin ascent!
        if (y<surface+20) {
            y=  surface;
            dy=  0;                  // Back to surface (dive ends).
            total += caught;
            caught=0;
        }
    }
  }
  void dive() {
    //// Stop the boat & start the dive.
    y=  surface+50;
    dy=l;
    caught=0;
  }
  void net( Fish f ) {
    //// Check if diver nets fish
    if (dy==0) return;                  // Not diving.
    if (dist(x,y, f.x,f.y) < 50) {      // Fish is near.
      if (dy>0) { 
        // Descending:  catch the fish.d
        caught++;
        f.reset(); 
      } else {
        // Lose the entire catch, if diver bumps into a fish.
        caught=0;
        background(255,0,0);    // Red flash!
      }
    }
  }
}

