Your browser does not support the canvas tag.

previous        Show / Hide Source        Download        next
//by: Nolan Grant, ID: 991412483, date: 04, October, 2017
//use arrow keys to control the shark, up to accelerate, left or right to rotate
//the shark is chill, it won't eat the other fish.

//shark
float sharkVectorPivotX = 200;
float sharkVectorPivotY = 190;
float sharkVectorHandleX = 200;
float sharkVectorHandleY = 215;
float rotation = 0;
float sharkThrustValue = 0.0;
float thrustBoundary = 1.0;
float thrustComponentX = (sharkVectorHandleX-sharkVectorPivotX)/25.0;
float thrustComponentY = (sharkVectorHandleY-sharkVectorPivotY)/25.0;
boolean isUpPressed = false;
boolean isLeftPressed = false;
boolean isRightPressed = false;
int sharkBaseColour = 127;
float tailSpeed = 0.002;
float leftRotationMomentum=0.0;
float RightRotationMomentum=0.0;

float heading= (atan((sharkVectorPivotY-sharkVectorHandleY)/(sharkVectorPivotX-sharkVectorHandleX)));

//fish 1/A
float fishAVectorPivotX = random(20, 380);
float fishAVectorPivotY = random(20, 380);
float fishARotation = random(0, PI*2.0);
float fishANoiseTime = random(0, 1000000);

//fish 2/B
float fishBVectorPivotX = random(20, 380);
float fishBVectorPivotY = random(20, 380);
float fishBRotation = random(0, PI*2.0);
float fishBNoiseTime = random(0, 1000000);

//fish 3/C
float fishCVectorPivotX = random(20, 380);
float fishCVectorPivotY = random(20, 380);
float fishCRotation = random(0, PI*2.0);
float fishCNoiseTime = random(0, 1000000);

//fish 4/D
float fishDVectorPivotX = random(20, 380);
float fishDVectorPivotY = random(20, 380);
float fishDRotation = random(0, PI*2.0);
float fishDNoiseTime = random(0, 1000000);

//fish 5/E
float fishEVectorPivotX = random(20, 380);
float fishEVectorPivotY = random(20, 380);
float fishERotation = random(0, PI*2.0);
float fishENoiseTime = random(0, 1000000);

//fish 6/F
float fishFVectorPivotX = random(20, 380);
float fishFVectorPivotY = random(20, 380);
float fishFRotation = random(0, PI*2.0);
float fishFNoiseTime = random(0, 1000000);

//fish 7/G
float fishGVectorPivotX = random(20, 380);
float fishGVectorPivotY = random(20, 380);
float fishGRotation = random(0, PI*2.0);
float fishGNoiseTime = random(0, 1000000);

//fish 8/H
float fishHVectorPivotX = random(20, 380);
float fishHVectorPivotY = random(20, 380);
float fishHRotation = random(0, PI*2.0);
float fishHNoiseTime = random(0, 1000000);

//fish 9/I
float fishIVectorPivotX = random(20, 380);
float fishIVectorPivotY = random(20, 380);
float fishIRotation = random(0, PI*2.0);
float fishINoiseTime = random(0, 1000000);

//fish 10/J
float fishJVectorPivotX = random(20, 380);
float fishJVectorPivotY = random(20, 380);
float fishJRotation = random(0, PI*2.0);
float fishJNoiseTime = random(0, 1000000);

//fish 11/K
float fishKVectorPivotX = random(20, 380);
float fishKVectorPivotY = random(20, 380);
float fishKRotation = random(0, PI*2.0);
float fishKNoiseTime = random(0, 1000000);

//fish 12/L
float fishLVectorPivotX = random(20, 380);
float fishLVectorPivotY = random(20, 380);
float fishLRotation = random(0, PI*2.0);
float fishLNoiseTime = random(0, 1000000);

//fish 13/M
float fishMVectorPivotX = random(20, 380);
float fishMVectorPivotY = random(20, 380);
float fishMRotation = random(0, PI*2.0);
float fishMNoiseTime = random(0, 1000000);

//fish 14/N
float fishNVectorPivotX = random(20, 380);
float fishNVectorPivotY = random(20, 380);
float fishNRotation = random(0, PI*2.0);
float fishNNoiseTime = random(0, 1000000);

void setup() {
  size(400, 400);
  frameRate(60);
}

void draw() {

  background(0, 0, 200);

  drawBackDrop();

  drawBottomFishGroup();

  drawShark();

  drawTopFishGroup();

  sharkRotationControl();
}

void sharkRotationControl() {

  //determines how the shark will rotate each frame
  //rotation speed has a minimum value of (rotationValue), but will increase for up to 30 frames if the key is not released or the opposite key pressed
  float rotationValue=(PI/128.0);
  float maxRotationMomentum=(PI/256.0);

  if (isLeftPressed==true) {
    rotation=rotation+(rotationValue)+leftRotationMomentum;
    leftRotationMomentum=leftRotationMomentum+(PI/(64.0*120.0));
    if (leftRotationMomentum>maxRotationMomentum) {
      leftRotationMomentum=maxRotationMomentum;
    }
  }
  if (isLeftPressed==false) {
    leftRotationMomentum=0.0;
  }

  if (isRightPressed==true) {
    rotation=rotation-(rotationValue)-RightRotationMomentum;
    RightRotationMomentum=RightRotationMomentum+(PI/(64.0*120.0));
    if (RightRotationMomentum>maxRotationMomentum) {
      RightRotationMomentum=maxRotationMomentum;
    }
  }
  if (isRightPressed==false) {
    RightRotationMomentum=0.0;
  }
}

void drawBackDrop() {

  //creates a backdrop of concentric circles with pulsing size
  for (int i = 0; i < 20; i++) {
    int fillColour = 45+(i*9);
    stroke(0, 0, fillColour-8, 255);
    float radius = sin(millis()*.001)*10+600-(i*30.0);
    fill(0, 0, fillColour, 255);
    ellipse(width/2.0, height/2.0, radius, radius);
  }
}

void keyPressed() {
 
  //determines if left arrow key has been pressed
  if (key == CODED) {
    if (keyCode == LEFT) {
      isLeftPressed=true;
      isRightPressed=false;
    } else {
    }

    //determines if right arrow key has been pressed
    if (key == CODED) {
      if (keyCode == RIGHT) {
        isRightPressed=true;
        isLeftPressed=false;
      } else {
      }

      //increases shark's forward thrust if up arrow key is pressed
      if (key == CODED) {
        if (keyCode == UP) {
          isUpPressed=true;
        }
        if (isUpPressed==true) {
          sharkThrustValue=3.0;
        } else {
        }
      }
    }
  }
}

void keyReleased() {

  if (key == CODED) {
    if (keyCode == UP) {
      isUpPressed=false;
      sharkThrustValue=1.0;
    }
  }

  if (key == CODED) {
    if (keyCode == LEFT) {
      isLeftPressed=false;
    }
  }

  if (key == CODED) {
    if (keyCode == RIGHT) {
      isRightPressed=false;
    }
  }
}

void drawShark() {

  //right eye
  ellipseMode(CENTER);
  stroke(255);
  strokeWeight(.5);
  fill(0);
  float eyesRX = sin(rotation-0.155)*-85.34+sharkVectorPivotX;
  float eyesRY = cos(rotation-0.155)*-85.34+sharkVectorPivotY;
  ellipse(eyesRX, eyesRY, 8, 8 );
  //left eye
  float eyesLX = sin(rotation+0.155)*-85.34+sharkVectorPivotX;
  float eyesLY = cos(rotation+0.155)*-85.34+sharkVectorPivotY;
  ellipse(eyesLX, eyesLY, 8, 8 );


  //nose
  stroke(sharkBaseColour);
  fill(sharkBaseColour);
  strokeWeight(2);
  float noseAX = sin(rotation-0.0261799)*-111.04+sharkVectorPivotX;
  float noseAY = cos(rotation-0.0261799)*-111.04+sharkVectorPivotY;
  float noseDX = sin(rotation+0.0261799)*-111.04+sharkVectorPivotX;
  float noseDY = cos(rotation+0.0261799)*-111.04+sharkVectorPivotY;
  float noseBX = sin(rotation-0.139626)*-93.9+sharkVectorPivotX;
  float noseBY = cos(rotation-0.139626)*-93.9+sharkVectorPivotY;
  float noseCX = sin(rotation+0.139626)*-93.9+sharkVectorPivotX;
  float noseCY = cos(rotation+0.139626)*-93.9+sharkVectorPivotY;
  quad(noseAX, noseAY, noseBX, noseBY, noseCX, noseCY, noseDX, noseDY);

  //head
  stroke(sharkBaseColour);
  fill(sharkBaseColour);
  float headAX = noseCX;
  float headAY = noseCY;
  float headBX = noseBX;
  float headBY = noseBY;
  float headCX = sin(rotation-0.349066)*-58.52+sharkVectorPivotX;
  float headCY = cos(rotation-0.349066)*-58.52+sharkVectorPivotY;
  float headDX = sin(rotation+0.349066)*-58.52+sharkVectorPivotX;
  float headDY = cos(rotation+0.349066)*-58.52+sharkVectorPivotY;
  quad(headAX, headAY, headBX, headBY, headCX, headCY, headDX, headDY);

  //torso
  stroke(sharkBaseColour);
  fill(sharkBaseColour);
  float torsoAX = headDX;
  float torsoAY = headDY;
  float torsoBX = headCX;
  float torsoBY = headCY;
  float torsoCX = sin(rotation-0.6038839)*-35.23+sharkVectorPivotX;
  float torsoCY = cos(rotation-0.6038839)*-35.23+sharkVectorPivotY;
  float torsoDX = sin(rotation+0.6038839)*-35.23+sharkVectorPivotX;
  float torsoDY = cos(rotation+0.6038839)*-35.23+sharkVectorPivotY;
  quad(torsoAX, torsoAY, torsoBX, torsoBY, torsoCX, torsoCY, torsoDX, torsoDY);

  //right fin
  stroke(sharkBaseColour);
  fill(sharkBaseColour);
  float rfinAX = torsoBX;
  float rfinAY = torsoBY;
  float rfinBX = sin(rotation-1.199041)*-55.54+sharkVectorPivotX;
  float rfinBY = cos(rotation-1.199041)*-55.54+sharkVectorPivotY;
  float rfinCX = sin(rotation-1.35263)*-55.32+sharkVectorPivotX;
  float rfinCY = cos(rotation-1.35263)*-55.32+sharkVectorPivotY;
  float rfinDX = torsoCX;
  float rfinDY = torsoCY;
  //right fin shadow
  stroke(94);
  line(rfinAX, rfinAY, rfinDX, rfinDY);

  //left fin
  stroke(sharkBaseColour);
  fill(sharkBaseColour);
  float lfinAX = torsoAX;
  float lfinAY = torsoAY;
  float lfinBX = sin(rotation+1.199041)*-55.54+sharkVectorPivotX;
  float lfinBY = cos(rotation+1.199041)*-55.54+sharkVectorPivotY;
  float lfinCX = sin(rotation+1.35263)*-55.32+sharkVectorPivotX;
  float lfinCY = cos(rotation+1.35263)*-55.32+sharkVectorPivotY;
  float lfinDX = torsoDX;
  float lfinDY = torsoDY;
  //left fin shadow
  stroke(94);
  line(lfinAX, lfinAY, lfinDX, lfinDY);

  //changes location of vertices at the fin tips to make the fin appear to dip when the shark turns in that direction
  //left turn
  if (isLeftPressed==true) {
    isRightPressed=false;
    lfinBX = sin(rotation+1.199041)*-46.54+sharkVectorPivotX;
    lfinBY = cos(rotation+1.199041)*-46.54+sharkVectorPivotY;
    lfinCX = sin(rotation+1.35263)*-46.32+sharkVectorPivotX;
    lfinCY = cos(rotation+1.35263)*-46.32+sharkVectorPivotY;
    noStroke();
    quad(lfinAX, lfinAY, lfinBX, lfinBY, lfinCX, lfinCY, lfinDX, lfinDY);
  } else {
    noStroke();
    quad(lfinAX, lfinAY, lfinBX, lfinBY, lfinCX, lfinCY, lfinDX, lfinDY);
  }
  //right turn
  if (isRightPressed==true) {
    isLeftPressed=false;
    rfinBX = sin(rotation-1.199041)*-46.54+sharkVectorPivotX;
    rfinBY = cos(rotation-1.199041)*-46.54+sharkVectorPivotY;
    rfinCX = sin(rotation-1.35263)*-46.32+sharkVectorPivotX;
    rfinCY = cos(rotation-1.35263)*-46.32+sharkVectorPivotY;
    noStroke();
    quad(rfinAX, rfinAY, rfinBX, rfinBY, rfinCX, rfinCY, rfinDX, rfinDY);
  } else {
    noStroke();
    quad(rfinAX, rfinAY, rfinBX, rfinBY, rfinCX, rfinCY, rfinDX, rfinDY);
  }

  //small fins near base of tail
  float tinyFinAX = sin(rotation)*4.54+sharkVectorPivotX;
  float tinyFinAY = cos(rotation)*4.54+sharkVectorPivotY;
  float tinyFinBX = sin(rotation+2.64346)*-34.54+sharkVectorPivotX;
  float tinyFinBY = cos(rotation+2.64346)*-34.54+sharkVectorPivotY;
  float tinyFinCX = sin(rotation-2.64346)*-34.54+sharkVectorPivotX;
  float tinyFinCY = cos(rotation-2.64346)*-34.54+sharkVectorPivotY;
  fill(sharkBaseColour);
  noStroke();
  triangle (tinyFinAX, tinyFinAY, tinyFinBX, tinyFinBY, tinyFinCX, tinyFinCY);

  //tail: Is made of 100 overlapping circles that whip at a rate linked to its speed as the shark moves
  for (int i = 0; i < 100; i++) {
    float tailSpeed = .002 * sharkThrustValue;
    float whipCoefficient = 111.0-i;
    float segmentRadius = 1.0+i;
    float tailSegmentX = (sin(rotation+(sin(millis()*tailSpeed)*(PI/whipCoefficient)))*segmentRadius+sharkVectorPivotX);
    float tailSegmentY = (cos(rotation+(sin(millis()*tailSpeed)*(PI/whipCoefficient)))*segmentRadius+sharkVectorPivotY);
    float sizeX = 30-i/3.5;
    float sizeY = 30-i/3.5;
    fill(sharkBaseColour);
    noStroke();
    ellipse(tailSegmentX, tailSegmentY, sizeX, sizeY);
  }

  //finds the pivot/root segment center of the fourth from last ellipse that makes up the tail
  //i=100-4  or 96, substitute in 96 for i as it would appear in the for loop
  float tailSpeed = .002 * sharkThrustValue;

  float whipCoefficient = 111.0-96;
  float rootSegmentRadius = 1.0+96;
  float rootTailSegmentX = (sin(rotation+(sin(millis()*tailSpeed)*(PI/whipCoefficient)))*rootSegmentRadius+sharkVectorPivotX);
  float rootTailSegmentY = (cos(rotation+(sin(millis()*tailSpeed)*(PI/whipCoefficient)))*rootSegmentRadius+sharkVectorPivotY);

  //finds the terminal/handle segment center of the last ellipse that makes up the tail
  //i=100-0  or 100, substitute in 0 for i as it would appear in the for loop
  float terminalWhipCoefficient = 111.0-100;
  float terminalSegmentRadius = 1.0+100;
  float terminalTailSegmentX = (sin(rotation+(sin(millis()*tailSpeed)*(PI/terminalWhipCoefficient)))*terminalSegmentRadius+sharkVectorPivotX);
  float terminalTailSegmentY = (cos(rotation+(sin(millis()*tailSpeed)*(PI/terminalWhipCoefficient)))*terminalSegmentRadius+sharkVectorPivotY);

  //shark tail fins: creates triangles with 2 points parented to the root/pivot and terminal/handle points and 1 point that rotates around the terminal point with the tail whip
  //bottom fin
  stroke(sharkBaseColour);
  strokeWeight(.5);
  fill(sharkBaseColour);
  triangle(terminalTailSegmentX, terminalTailSegmentY, rootTailSegmentX, rootTailSegmentY,
    (sin(rotation+(sin((millis())*tailSpeed)))*25.0)+terminalTailSegmentX,
    (cos(rotation+(sin((millis())*tailSpeed)))*25.0)+terminalTailSegmentY);  
  //top fin
  fill(sharkBaseColour);
  triangle(terminalTailSegmentX, terminalTailSegmentY, rootTailSegmentX, rootTailSegmentY,
    (sin(rotation+((sin((millis())*tailSpeed)))+(sin((millis())*tailSpeed)))*35.0)+terminalTailSegmentX,
    (cos(rotation+((sin((millis())*tailSpeed)))+(sin((millis())*tailSpeed)))*35.0)+terminalTailSegmentY);

  //lower body
  noStroke();
  fill(sharkBaseColour);
  float tailX=sin(rotation+0.25)*39.0+sharkVectorPivotX;
  float tailY=cos(rotation+0.25)*39.0+sharkVectorPivotY; 
  float tailBX=sin(rotation-0.25)*39.0+sharkVectorPivotX;
  float tailBY=cos(rotation-0.25)*39.0+sharkVectorPivotY;
  quad(torsoDX, torsoDY, torsoCX, torsoCY, tailX, tailY, tailBX, tailBY);

  //dorsal fin
  stroke(94);
  strokeWeight(1);
  fill(sharkBaseColour);
  float dFinAX=sin(rotation)*-35.0+sharkVectorPivotX;
  float dFinAY=cos(rotation)*-35.0+sharkVectorPivotY;
  float dFinBX=sin(rotation-0.3036873)*-16.76+sharkVectorPivotX;
  float dFinBY=cos(rotation-0.3036873)*-16.76+sharkVectorPivotY;
  float dFinCX=sin(rotation)*5.0+sharkVectorPivotX;
  float dFinCY=cos(rotation)*5.0+sharkVectorPivotY;
  float dFinDX=sin(rotation+0.3036873)*-16.76+sharkVectorPivotX;
  float dFinDY=cos(rotation+0.3036873)*-16.76+sharkVectorPivotY;
  quad(dFinAX, dFinAY, dFinBX, dFinBY, dFinCX, dFinCY, dFinDX, dFinDY);

  //front gills
  stroke(64);
  strokeWeight(1);
  float gillAX = sin(rotation-0.143117)*-73.72+sharkVectorPivotX;
  float gillAY = cos(rotation-0.143117)*-73.72+sharkVectorPivotY;
  float gillBX = sin(rotation-0.2408554)*-76.2+sharkVectorPivotX;
  float gillBY = cos(rotation-0.2408554)*-76.2+sharkVectorPivotY;
  line(gillAX, gillAY, gillBX, gillBY);

  float gillCX = sin(rotation+0.143117)*-73.72+sharkVectorPivotX;
  float gillCY = cos(rotation+0.143117)*-73.72+sharkVectorPivotY;
  float gillDX = sin(rotation+0.2408554)*-76.2+sharkVectorPivotX;
  float gillDY = cos(rotation+0.2408554)*-76.2+sharkVectorPivotY;
  line(gillCX, gillCY, gillDX, gillDY);

  //middle gills
  float gillIX = sin(rotation-0.1780236)*-68.07+sharkVectorPivotX;
  float gillIY = cos(rotation-0.1780236)*-68.07+sharkVectorPivotY;
  float gillJX = sin(rotation-0.26229)*-71.40+sharkVectorPivotX;
  float gillJY = cos(rotation-0.26229)*-71.40+sharkVectorPivotY;
  line(gillIX, gillIY, gillJX, gillJY);

  float gillKX = sin(rotation+0.1780236)*-68.07+sharkVectorPivotX;
  float gillKY = cos(rotation+0.1780236)*-68.07+sharkVectorPivotY;
  float gillLX = sin(rotation+0.26229)*-71.40+sharkVectorPivotX;
  float gillLY = cos(rotation+0.26229)*-71.40+sharkVectorPivotY;
  line(gillKX, gillKY, gillLX, gillLY);

  //back gills
  stroke(64);
  strokeWeight(1);
  float gillEX = sin(rotation-0.2181662)*-63.31+sharkVectorPivotX;
  float gillEY = cos(rotation-0.2181662)*-63.31+sharkVectorPivotY;
  float gillFX = sin(rotation-0.29147)*-66.48+sharkVectorPivotX;
  float gillFY = cos(rotation-0.29147)*-66.48+sharkVectorPivotY;
  line(gillEX, gillEY, gillFX, gillFY);

  float gillGX = sin(rotation+0.2181662)*-63.31+sharkVectorPivotX;
  float gillGY = cos(rotation+0.2181662)*-63.31+sharkVectorPivotY;
  float gillHX = sin(rotation+0.29147)*-66.48+sharkVectorPivotX;
  float gillHY = cos(rotation+0.29147)*-66.48+sharkVectorPivotY;
  line(gillGX, gillGY, gillHX, gillHY);

  //shark rotation system
  sharkVectorPivotX=sin(rotation)*25.0+sharkVectorHandleX;
  sharkVectorPivotY=cos(rotation)*25.0+sharkVectorHandleY;

  //shark movement system, calculates directional speed by using vector math, sharkThrustValue is magnitude and X and Y components are calculated.
  thrustComponentX=(sharkVectorHandleX-sharkVectorPivotX)/25.0*sharkThrustValue*thrustBoundary;
  thrustComponentY=(sharkVectorHandleY-sharkVectorPivotY)/25.0*sharkThrustValue*thrustBoundary;
  sharkVectorHandleX=sharkVectorHandleX+thrustComponentX;
  sharkVectorHandleY=sharkVectorHandleY+thrustComponentY;

  //causes shark to move to opposite side of screen if it goes offscreen
  int sharkBoundary = 165;
  if (sharkVectorHandleY <-sharkBoundary) {
    sharkVectorHandleY=515;
  }
  if (sharkVectorHandleY >height + sharkBoundary) {
    sharkVectorHandleY=-15;
  }
  if (sharkVectorHandleX <-sharkBoundary) {
    sharkVectorHandleX=515;
  }
  if (sharkVectorHandleX >width+sharkBoundary) {
    sharkVectorHandleX=-15;
  }

  //hard resets shark to center if it somehow escapes the play area
  if ((sharkVectorPivotX >600) || (sharkVectorPivotX<(-200)) ||(sharkVectorPivotY<(-200))||(sharkVectorPivotY>600)) {
    sharkVectorPivotX=200;
    sharkVectorPivotY=200;
    rotation=0;
  } else {
  }
}

//unique fish functions, arguments are the (fish number, x pivot vector, y pivot vector, thrust, noisetime) for that unique fish
//groups half the fish (A/1 to G/7) into a function. These will swim below the shark to add a sense of depth.
void drawTopFishGroup() {
  drawFishA();

  drawFishB();

  drawFishC();

  drawFishD();

  drawFishE();

  drawFishF();

  drawFishG();
}

//groups half the fish (H/8 to N/14) into a function. These will swim above the shark to add a sense of depth.
void drawBottomFishGroup() {
  drawFishH();

  drawFishI();

  drawFishJ();

  drawFishK();

  drawFishL();

  drawFishM();

  drawFishN();
}

void drawFishA() {
  drawAnyFish(1, fishAVectorPivotX, fishAVectorPivotY, 1.0, fishARotation, fishANoiseTime);
}
void drawFishB() {
  drawAnyFish(2, fishBVectorPivotX, fishBVectorPivotY, 1.0, fishBRotation, fishBNoiseTime);
}
void drawFishC() {
  drawAnyFish(3, fishCVectorPivotX, fishCVectorPivotY, 1.0, fishCRotation, fishDNoiseTime);
}
void drawFishD() {
  drawAnyFish(4, fishDVectorPivotX, fishDVectorPivotY, 1.0, fishDRotation, fishDNoiseTime);
}
void drawFishE() {
  drawAnyFish(5, fishEVectorPivotX, fishEVectorPivotY, 1.0, fishERotation, fishENoiseTime);
}
void drawFishF() {
  drawAnyFish(6, fishFVectorPivotX, fishFVectorPivotY, 1.0, fishFRotation, fishFNoiseTime);
}
void drawFishG() {
  drawAnyFish(7, fishGVectorPivotX, fishGVectorPivotY, 1.0, fishGRotation, fishGNoiseTime);
}
void drawFishH() {
  drawAnyFish(8, fishHVectorPivotX, fishHVectorPivotY, 1.0, fishHRotation, fishHNoiseTime);
}
void drawFishI() {
  drawAnyFish(9, fishIVectorPivotX, fishIVectorPivotY, 1.0, fishIRotation, fishINoiseTime);
}
void drawFishJ() {
  drawAnyFish(10, fishJVectorPivotX, fishJVectorPivotY, 1.0, fishJRotation, fishJNoiseTime);
}
void drawFishK() {
  drawAnyFish(11, fishKVectorPivotX, fishKVectorPivotY, 1.0, fishKRotation, fishKNoiseTime);
}
void drawFishL() {
  drawAnyFish(12, fishLVectorPivotX, fishLVectorPivotY, 1.0, fishLRotation, fishLNoiseTime);
}
void drawFishM() {
  drawAnyFish(13, fishMVectorPivotX, fishMVectorPivotY, 1.0, fishMRotation, fishMNoiseTime);
}
void drawFishN() {
  drawAnyFish(14, fishNVectorPivotX, fishNVectorPivotY, 1.0, fishNRotation, fishNNoiseTime);
}

//function that will draw any of the unique fish by using their global variables
void drawAnyFish( int uniqueFishNumber, float localFishPivotX, float localFishVectorY, float fishThrust, float localFishRotation, float localFishNoiseTime) {

  //determines what unique fish function is calling drawAnyFish and sets local variables to unique fish's corresponding global variables
  int localFishNumber = 0;
  localFishNumber = uniqueFishNumber;

  if (localFishNumber==1) {
    localFishPivotX = fishAVectorPivotX;
    localFishVectorY = fishAVectorPivotY;
    localFishRotation = fishARotation;
    localFishNoiseTime = fishANoiseTime;
  }
  if (localFishNumber==2) {
    localFishPivotX = fishBVectorPivotX;
    localFishVectorY = fishBVectorPivotY;
    localFishRotation = fishBRotation;
    localFishNoiseTime = fishBNoiseTime;
  }
  if (localFishNumber==3) {
    localFishPivotX = fishCVectorPivotX;
    localFishVectorY = fishCVectorPivotY;
    localFishRotation = fishCRotation;
    localFishNoiseTime = fishCNoiseTime;
  }
  if (localFishNumber==4) {
    localFishPivotX = fishDVectorPivotX;
    localFishVectorY = fishDVectorPivotY;
    localFishRotation = fishDRotation;
    localFishNoiseTime = fishDNoiseTime;
  }
  if (localFishNumber==5) {
    localFishPivotX = fishEVectorPivotX;
    localFishVectorY = fishEVectorPivotY;
    localFishRotation = fishERotation;
    localFishNoiseTime = fishENoiseTime;
  }
  if (localFishNumber==6) {
    localFishPivotX = fishFVectorPivotX;
    localFishVectorY = fishFVectorPivotY;
    localFishRotation = fishFRotation;
    localFishNoiseTime = fishFNoiseTime;
  }
  if (localFishNumber==7) {
    localFishPivotX = fishGVectorPivotX;
    localFishVectorY = fishGVectorPivotY;
    localFishRotation = fishGRotation;
    localFishNoiseTime = fishGNoiseTime;
  }
  if (localFishNumber==8) {
    localFishPivotX = fishHVectorPivotX;
    localFishVectorY = fishHVectorPivotY;
    localFishRotation = fishHRotation;
    localFishNoiseTime = fishHNoiseTime;
  }
  if (localFishNumber==9) {
    localFishPivotX = fishIVectorPivotX;
    localFishVectorY = fishIVectorPivotY;
    localFishRotation = fishIRotation;
    localFishNoiseTime = fishINoiseTime;
  }
  if (localFishNumber==10) {
    localFishPivotX = fishJVectorPivotX;
    localFishVectorY = fishJVectorPivotY;
    localFishRotation = fishJRotation;
    localFishNoiseTime = fishJNoiseTime;
  }
  if (localFishNumber==11) {
    localFishPivotX = fishKVectorPivotX;
    localFishVectorY = fishKVectorPivotY;
    localFishRotation = fishKRotation;
    localFishNoiseTime = fishKNoiseTime;
  }
  if (localFishNumber==12) {
    localFishPivotX = fishLVectorPivotX;
    localFishVectorY = fishLVectorPivotY;
    localFishRotation = fishLRotation;
    localFishNoiseTime = fishLNoiseTime;
  }
  if (localFishNumber==13) {
    localFishPivotX = fishMVectorPivotX;
    localFishVectorY = fishMVectorPivotY;
    localFishRotation = fishMRotation;
    localFishNoiseTime = fishMNoiseTime;
  }
  if (localFishNumber==14) {
    localFishPivotX = fishNVectorPivotX;
    localFishVectorY = fishNVectorPivotY;
    localFishRotation = fishNRotation;
    localFishNoiseTime = fishNNoiseTime;
  }

  //local fish variables
  float localFishVectorHandleX = (sin(localFishRotation)*8.0)+localFishPivotX;
  float localFishVectorHandleY = (cos(localFishRotation)*8.0)+localFishVectorY;
  float fishThrustComponentX = 0.0;
  float fishThrustComponentY = 0.0;
  float fishTailCX =sin(localFishRotation+(PI/1.1))*-9.0+localFishPivotX;
  float fishTailCY =cos(localFishRotation+(PI/1.1))*-9.0+localFishVectorY;
  float fishTailDX =sin(localFishRotation-(PI/1.1))*-9.0+localFishPivotX;
  float fishTailDY =cos(localFishRotation-(PI/1.1))*-9.0+localFishVectorY;

  //fish body
  stroke(150, 108, 10);
  strokeWeight(1);
  fill(255, 200, 20);
  ellipse(localFishPivotX, localFishVectorY, 7, 7);

  //fish tail
  noStroke();
  fill(255, 200, 20, 175);
  triangle(localFishPivotX, localFishVectorY, fishTailCX, fishTailCY, fishTailDX, fishTailDY);

  //fish rotation system
  localFishVectorHandleX=sin(localFishRotation)*8.0+localFishPivotX;
  localFishVectorHandleY = cos(localFishRotation)*8.0+localFishVectorY;

  //fish movement system
  fishThrustComponentX=(localFishPivotX-localFishVectorHandleX)/16.0*fishThrust;
  fishThrustComponentY=(localFishVectorY-localFishVectorHandleY)/16.0*fishThrust;
  localFishPivotX=localFishPivotX+fishThrustComponentX;
  localFishVectorY=localFishVectorY+fishThrustComponentY;

  //bounces fish off of boundaries upon collision and sets outgoing angle to incoming angle
  //finds angle between fish and wall, then multiples that by 2, then adds or subtracts that angle to rotation depending on angle of approach
  int topLeftBoundarySize=0;
  int bottomRightBoundarySize=400-topLeftBoundarySize;

  //top boundary, if fish is facing left
  if ((localFishVectorY <topLeftBoundarySize) && (localFishVectorHandleX > localFishPivotX)) {
    localFishRotation=localFishRotation + (2.0*(atan((localFishVectorHandleY-localFishVectorY)/(localFishVectorHandleX-localFishPivotX))));
  }

  //top boundary, if fish is facing right
  if ((localFishVectorY <topLeftBoundarySize) && (localFishVectorHandleX < localFishPivotX)) {
    localFishRotation= localFishRotation - (2.0*(atan((localFishVectorY-localFishVectorHandleY)/(localFishVectorHandleX-localFishPivotX))));
  }

  //left boundary, if fish is facing up
  if ((localFishPivotX <topLeftBoundarySize) && (localFishVectorHandleY > localFishVectorY)) {
    localFishRotation=localFishRotation - (2.0*(atan((localFishVectorHandleX-localFishPivotX)/(localFishVectorHandleY-localFishVectorY))));
  }

  //left boundary, if fish is facing down
  if ((localFishPivotX <topLeftBoundarySize) && (localFishVectorHandleY < localFishVectorY)) {
    localFishRotation=localFishRotation + (2.0*(atan((localFishPivotX-localFishVectorHandleX)/(localFishVectorHandleY-localFishVectorY))));
  }

  //bottom boundary, if fish is facing left
  if ((localFishVectorY >bottomRightBoundarySize) && (localFishVectorHandleX > localFishPivotX)) {
    localFishRotation=localFishRotation + (2.0*(atan((localFishVectorHandleY-localFishVectorY)/(localFishVectorHandleX-localFishPivotX))));
  }

  //bottom boundary, if fish is facing right
  if ((localFishVectorY >bottomRightBoundarySize) && (localFishVectorHandleX < localFishPivotX)) {
    localFishRotation=localFishRotation - (2.0*(atan((localFishVectorY-localFishVectorHandleY)/(localFishVectorHandleX-localFishPivotX))));
  }

  //right boundary, if fish is facing up
  if ((localFishPivotX >bottomRightBoundarySize) && (localFishVectorHandleY>localFishVectorY)) {
    localFishRotation=localFishRotation + (2.0*(atan((localFishVectorHandleX-localFishPivotX)/(localFishVectorY-localFishVectorHandleY))));
  }

  //right boundary, if fish is facing down
  if ((localFishPivotX >bottomRightBoundarySize) && (localFishVectorHandleY < localFishVectorY) && (localFishVectorHandleX<localFishPivotX)) {
    localFishRotation=localFishRotation - (2.0*(atan((localFishPivotX-localFishVectorHandleX)/(localFishVectorY-localFishVectorHandleY))));
  } else {
  }

  //sets the noise that controls fish's random turning
  localFishNoiseTime = localFishNoiseTime +0.1;
  float boundaryRotDampener = 1.0;
  int BoundaryRotDampenerOffset = -8;
  //decrease fish's random movements when near boundaries to mitigate fish steering back into boundaries repeatedly
  if ((localFishPivotX <topLeftBoundarySize-BoundaryRotDampenerOffset) || (localFishPivotX>bottomRightBoundarySize+BoundaryRotDampenerOffset) ||
    (localFishVectorY<topLeftBoundarySize-BoundaryRotDampenerOffset)||(localFishVectorY>bottomRightBoundarySize+BoundaryRotDampenerOffset)) {
    boundaryRotDampener=0.5;
  }
  //applies noise to fish's rotation, with consideration for if the fish is near the boundary
  float fishRotationRange = PI/72.0;
  float fishNoise = ((noise(localFishNoiseTime))-.5)*2.0;
  float fishJitters = fishNoise * fishRotationRange * boundaryRotDampener ;
  localFishRotation = localFishRotation + fishJitters;

  //resets escaped fish to within boundary if it somehow escapes
  if (localFishVectorY<topLeftBoundarySize-3) {
    localFishVectorY=topLeftBoundarySize+3;
  }
  if (localFishVectorY>bottomRightBoundarySize+3) {
    localFishVectorY=bottomRightBoundarySize-3;
  }
  if (localFishPivotX<topLeftBoundarySize-3) {
    localFishPivotX=topLeftBoundarySize+3;
  }
  if (localFishPivotX>bottomRightBoundarySize+3) {
    localFishPivotX=bottomRightBoundarySize-3;
  }

  //at end of function, stores local values of the unique fish to that fish's global variable
  if (localFishNumber==1) {
    fishAVectorPivotX = localFishPivotX;
    fishAVectorPivotY = localFishVectorY;
    fishARotation = localFishRotation;
    fishANoiseTime = localFishNoiseTime;
  }
  if (localFishNumber==2) {
    fishBVectorPivotX = localFishPivotX;
    fishBVectorPivotY = localFishVectorY;
    fishBRotation = localFishRotation;
    fishBNoiseTime = localFishNoiseTime;
  }
  if (localFishNumber==3) {
    fishCVectorPivotX = localFishPivotX;
    fishCVectorPivotY = localFishVectorY;
    fishCRotation = localFishRotation;
    fishCNoiseTime = localFishNoiseTime;
  }
  if (localFishNumber==4) {
    fishDVectorPivotX = localFishPivotX;
    fishDVectorPivotY = localFishVectorY;
    fishDRotation = localFishRotation;
    fishDNoiseTime = localFishNoiseTime;
  }
  if (localFishNumber==5) {
    fishEVectorPivotX = localFishPivotX;
    fishEVectorPivotY = localFishVectorY;
    fishERotation = localFishRotation;
    fishENoiseTime = localFishNoiseTime;
  }
  if (localFishNumber==6) {
    fishFVectorPivotX = localFishPivotX;
    fishFVectorPivotY = localFishVectorY;
    fishFRotation = localFishRotation;
    fishFNoiseTime = localFishNoiseTime;
  }
  if (localFishNumber==7) {
    fishGVectorPivotX = localFishPivotX;
    fishGVectorPivotY = localFishVectorY;
    fishGRotation = localFishRotation;
    fishGNoiseTime = localFishNoiseTime;
  }
  if (localFishNumber==8) {
    fishHVectorPivotX = localFishPivotX;
    fishHVectorPivotY = localFishVectorY;
    fishHRotation = localFishRotation;
    fishHNoiseTime = localFishNoiseTime;
  }
  if (localFishNumber==9) {
    fishIVectorPivotX = localFishPivotX;
    fishIVectorPivotY = localFishVectorY;
    fishIRotation = localFishRotation;
    fishINoiseTime = localFishNoiseTime;
  }
  if (localFishNumber==10) {
    fishJVectorPivotX = localFishPivotX;
    fishJVectorPivotY = localFishVectorY;
    fishJRotation = localFishRotation;
    fishJNoiseTime = localFishNoiseTime;
  }
  if (localFishNumber==11) {
    fishKVectorPivotX = localFishPivotX;
    fishKVectorPivotY = localFishVectorY;
    fishKRotation = localFishRotation;
    fishKNoiseTime = localFishNoiseTime;
  }
  if (localFishNumber==12) {
    fishLVectorPivotX = localFishPivotX;
    fishLVectorPivotY = localFishVectorY;
    fishLRotation = localFishRotation;
    fishLNoiseTime = localFishNoiseTime;
  }
  if (localFishNumber==13) {
    fishMVectorPivotX = localFishPivotX;
    fishMVectorPivotY = localFishVectorY;
    fishMRotation = localFishRotation;
    fishMNoiseTime = localFishNoiseTime;
  }
  if (localFishNumber==14) {
    fishNVectorPivotX = localFishPivotX;
    fishNVectorPivotY = localFishVectorY;
    fishNRotation = localFishRotation;
    fishNNoiseTime = localFishNoiseTime;
  }
}