int[] center = new int[2];
FishPart[] fishbody = new FishPart[8];
int fishtailSections = 6;
FishPart[] fishtail = new FishPart[fishtailLength * fishtailSections];
int fishfinLowLength = 3;
int fishfinLowSections = 4;
FishPart[] fishfinLow = new FishPart[fishfinLowLength * fishfinLowSections];
fishhead = new FishPart(center[0], center[1], 6);
for(int i = 0; i < fishbody.length; i++){
fishbody[i] = new FishPart(center[0], center[1], int(30 * (sin(i * 0.5) + 1)));
for(int j = 0; j < fishtailSections; j++){
for(int i = 0; i < fishtailLength; i++){
fishtail[fishtailLength * j + i] = new FishPart(center[0], center[1], int((30 - j*5) * (sin(i * 0.3) + 1)));
for(int j = 0; j < fishfinLowSections; j++){
for(int i = 0; i < fishfinLowLength; i++){
fishfinLow[fishfinLowLength * j + i] = new FishPart(center[0], center[1], int((20 - j*5) * (sin(i * 0.2) + 1)));
for(int i = fishbody.length - 1; i >= 0; i--){
fishbody[i].seek(fishhead.position);
fishbody[i].display(fishhead.position, fishhead.size);
fishbody[i].seek(fishbody[i-1].position);
fishbody[i].display(fishbody[i - 1].position, fishbody[i - 1].size);
for(int j = 0; j < fishtailSections; j++){
for(int i = fishtailLength - 1; i >= 0; i--){
fishtail[fishtailLength * j + i].seek(fishbody[fishbody.length - 1].position);
fishtail[fishtailLength * j + i].display(
fishbody[fishbody.length - 1].position,
fishbody[fishbody.length - 1]. size - j * 3);
fishtail[fishtailLength * j + i].seek(fishtail[i-1].position);
fishtail[fishtailLength * j + i].display(
fishtail[fishtailLength * j + i - 1].position,
fishtail[fishtailLength * j + i - 1].size);
fishtail[fishtailLength * j + i].sine(i);
fishtail[fishtailLength * j + i].update();
for(int j = 0; j < fishfinLowSections; j++){
for(int i = fishfinLowLength - 1; i >= 0; i--){
if(fishhead.position.x < fishbody[1].position.x - 1){
finOffset = fishbody[2].size / 3;
if(fishhead.position.x > fishbody[1].position.x + 1){
finOffset = -fishbody[2].size / 3;
PVector target = new PVector(
fishbody[2].position.x + finOffset,
fishbody[2].position.y + fishbody[2].size / 2);
fishfinLow[fishfinLowLength * j + i].seek(target);
fishfinLow[fishfinLowLength * j + i].display(target, fishbody[2].size / 3 - (j + 1) * 3);
fishfinLow[fishfinLowLength * j + i].seek(fishfinLow[i-1].position);
fishfinLow[fishfinLowLength * j + i].display(
fishfinLow[fishfinLowLength * j + i - 1].position,
fishfinLow[fishfinLowLength * j + i - 1].size);
fishfinLow[fishfinLowLength * j + i].sine(i);
fishfinLow[fishfinLowLength * j + i].update();
PVector mousePos = new PVector(mouseX, mouseY);
fishhead.close(mousePos);
float eyeSizeScaled = abs(fishhead.position.x - fishbody[1].position.x) < eyeSize ?
eyeSizeScaled = abs(fishhead.position.x - fishbody[1].position.x):
if(fishhead.position.x < fishbody[1].position.x - 1){
ellipse(fishbody[1].position.x + eyeSize, fishbody[1].position.y - eyeSize * 2, eyeSizeScaled, eyeSize);
if(fishhead.position.x > fishbody[1].position.x + 1){
ellipse(fishbody[1].position.x - eyeSize, fishbody[1].position.y - eyeSize * 2, eyeSizeScaled, eyeSize);
FishPart(int posX, int posY, int _size) {
position = new PVector(posX, posY);
velocity = new PVector(0, 0);
acceleration = new PVector(0, 0);
velocity.add(acceleration);
void applyForce(PVector force) {
void seek(PVector target) {
PVector desired = PVector.sub(target, position);
float m = map(d, 0, size/2, 0, maxspeed);
desired.setMag(maxspeed);
PVector steer = PVector.sub(desired, velocity);
position.x += (-0.5 + noise(position.x, size, millis() * 0.001)) * 3;
position.y += (-0.5 + noise(position.y, size, millis() * 0.001)) * 3;
float movX = sin(millis() * 0.002 + offset + 200) * 0.5;
float movY = sin(millis() * 0.001 + offset);
void display(PVector targetPos, float targetScale) {
line(position.x, position.y + size, targetPos.x, targetPos.y + targetScale);
line(position.x, position.y - size, targetPos.x, targetPos.y - targetScale);
if(position.x > targetPos.x + 1){
line(position.x + size/2, position.y, targetPos.x + targetScale/2, targetPos.y);
if(position.x < targetPos.x - 1){
line(position.x - size/2, position.y, targetPos.x - targetScale/2, targetPos.y);
void close(PVector target) {
int dir = position.x > target.x ? 1 : -1;
line(position.x, position.y + size, position.x, position.y - size);
line(position.x + size/2 * dir, position.y, position.x, position.y);