How to Draw Fish with Math (Part 2)

For absolute beginners

Rasa Ichimori
3 min readJan 21, 2023

Alright, so we’ve now made a head! Pat yourselves on the back (or head). Our next step is as easy as the first! We are just drawing out the fins this time.

Drawing the Fins

points for the fins

Here are the coordinates for the points:

Point 0: (0, 0)

Point 1: (-1.5 *s, -1.5 *s)

Point 2: (-1.5 *s, -0.5 *s)

Point 3: (0, 0)

Point 4: (-1.5 *s, 0.5 *s)

Point 5: (-1.5 *s, 1.5 *s)

Point 6: (0, 0)

Notice that in the picture, Point 0 and Point 3 are not visible. This is because Points 0, 3, and 6 all have the same coordinates of (0, 0)! Basically, Points 0, and 3, are hiding behind Point 6. Because Point 6 was the last to be drawn, it is what we see. Now (0,0) is starting to look like the center.

Now what?

Creating Dynamic Points

I think its pretty cool that we have a head and some fins, but they are just sitting there on my screen! It doesn’t move and its getting boring. Let’s add some user interactivity and movement!

On p5.js, there is a pretty nifty set of variables called mouseX and mouseY. These are variables that aways return your mouse’s position on the screen! How useful! Now I want to have the fish follow my mouse! Essentially, head and fins need to be where my mouse is.

Now there are two ways to do that. One way is to redo all the hard work you’ve done, and add the variable “mouseX” to the x coordinates for each point, and the variable “mouseY” to the y coordinates for each point. That would look like this for example:

Point 1: (mouseX + (-1.5*s), mouseY + (-1.5*s))

Sounds tedious right? Even more so when you consider that you have to do that for all of the points for the head as well.

Luckily, there is a second way, and that is by using another nifty p5 function called “translate()”. For this to work, you’d need to use “push()” and “pop()”

push();
translate(100,100);
ellipse(0,0,30);
pop();

// same position on screen
ellipse(100,100,30);

Push and pop serve as a container for the translate. Whatever happens within the push and pop, stays there. Translate will shift all the objects under it by a certain x and y amount. Perfect for what we are trying to do here!

on top of our curve vertex code, let’s add translate. And then lets wrap everything in a push and pop

function drawFin(s) {
push();
translate(100,100);
beginShape();
curveVertex(0,0);
curveVertex(s*-1.5,s*1.5);
curveVertex(s*-1.5,s*0.5);
curveVertex(0,0);
curveVertex(s*-1.5,s*-0.5);
curveVertex(s*-1.5,s*-1.5);
curveVertex(0,0);
endShape(CLOSE);
pop();
}

drawFin(50);

Notice that with the translate, it is shifted by the amount you put! Lets put our favorite “mouseX” and “mouseY” for the translate coordinates! Better yet, lets have our drawFin function also take in an x and y parameter that you can put your mouse variables in like this:

function drawFin(x,y,s) {
push();
translate(x,y);
beginShape();
curveVertex(0,0);
curveVertex(s*-1.5,s*1.5);
curveVertex(s*-1.5,s*0.5);
curveVertex(0,0);
curveVertex(s*-1.5,s*-0.5);
curveVertex(s*-1.5,s*-1.5);
curveVertex(0,0);
endShape(CLOSE);
pop();
}

function draw(){
background(255);
drawFin(mouseX, mouseY, 50);
}

The draw function is a loop which allows for constant updating when the mouse moves. The background is also there to reset the frame before drawing the fish.

Add do the same thing for our head function and we now have a dynamic fish and head that moves to our mouse! Things are starting turn out!

--

--