We will write code to generate a wavy animation of a grid where each box will have many nested boxes and they will be animating independently, creating an illusion of a portal. We will be using the p5js web editor which has all the setup for animation.

There are many elements in the animation above and we will be breaking it down into small tutorials as follows:

Drawing a square (or polygon with N number of sides) from two points.

Creating the portal effect using recursion.

Arranging squares into a grid and creating wave animation.

**Drawing a square or polygon from two points**

When we open the p5js web editor we will have some default code for the initial setup and draw function which will be running each frame.

For a thicker line, we can use a stroke weight of 3 using strokeWeight() function. For a little easy calculation, we can use the degree as angle mode instead of radians.

For drawing a polygon I will create a helper function which will have all the code drawing the square or a polygon of N number of sides.

So our initial code will be as follows:

We have start(x,y) and end(x,y) points which are two points of the base side. Let's say we have a vector v = end - start.

The general idea behind making a polygon is that we need to find NUM_OF_SIDES - 2 points, and connect each point with the previous one. So at the start, we have a vector v, now for the next point we can rotate the vector to a certain angle theta, and it will give us a new vector N, and then for the new point C, we can add the vector N with the previous point.

V = end - start

Nx = cos(theta) * Vx - sin(theta) * Vy

Ny = sin(theta) * Vx + cos(theta) * Vy

C = start + N

The angle between two sides of a polygon having all sides (n) of equal length can be calculated using the following steps:

Use the formula:

*angle = (n-2) * 180 / n***,**where n is the number of sides of the polygon.For example, in the case of a square, the angle between two sides would be: angle = (4-2) * 180 / 4 = 90 degrees

In the case of an equilateral triangle, the angle between two sides would be: angle = (3-2) * 180 / 3 = 60 degrees

So, the new code for draw_polygon is as follows:

If we use this draw_polygon function in the draw(), we get the following image.

**Creating the portal effect using recursion**

Here the core idea is that we will be drawing multiple polygons inside one another using recursion.

We can use the draw_polygon method for drawing nested polygons but for that, we need two points (start and end).

We can find a new point on the edge using linear interpolation. The two points that define the vector are usually referred to as the start point (P0) and the endpoint (P1). The new point (P) that you want to find is the point that lies on the vector at a distance of t (0 <= t <= 1) from the start point.

The coordinates of the new point P can be found using the following equations:

Px = (1-t) * P0x + t * P1x

Py = (1-t) * P0y + t * P1y

Where P0x, P0y are the x and y coordinates of the start point, and P1x, P1y are the x and y coordinates of the endpoint.

Now we need to decide how many levels of nested polygons we want. And to end the recursion for level 0 we will just return.

We can animate the nested polygons by changing the value of the ratio in each frame.

So the final code for drawing nested polygons(here the number of sides we are keeping as 4 for square) should look something like this.

**Arranging squares into a grid and creating wave animation**

We can divide the canvas into 4 quadrants and in each quadrant, we want a certain number of boxes in each axis. Let's save that in a variable names numOfBoxes. We can have a different number of boxes on each axis but for simplicity, I'm keeping the same for both the x and y-axis.

Now we can use nested for loop for creating the grid structure. Refer to the below code and the image we get after modifying the code in the draw function:

As we can see boxes are perfectly aligned on the grid but no animation is there as I have fixed the value for loopRatio to 0.3. For animating the boxes we can use a sin() function which we have discussed in the previous section.

let loopRatio = (sin((0.05*millis())%360)+1)/2;

Now for the final part where we will be adding waves in the animation, the idea behind this kind of animation is that we just need to add an offset between each box.

For animating a wave from top to bottom we can add an offset which will depend on the index of each row.

let loopRatio = (sin((0.05*millis() - indexY * 10)%360)+1)/2;

Similarly, for the left-to-right wave, we can vary the offset using indexX variable instead of indexY.

For the animation, we have shown at the start of this tutorial where we have a wave from one corner to another, for that we will have an offset value which will be a function of indexX and indexY.

let loopRatio = (sin((0.05*millis() - indexX * 10 - indexY * 10)%360)+1)/2;

So the final code in the draw function will be as below:

So in this tutorial, we learned about drawing a polygon of N side from a single vector which is one the side (base) of the polygon. We then learned about linear interpolation for getting new points on a vector and then using recursion we created a nested polygon structure. We used the sine function for creating a nice animated loop which gives the portal opening and closing look and then using for loop we arranged each box on a grid. And finally by just adding offset to the loop ratio we created a nice wave pattern in the grid.

You can find my sketch and code here.

Hope you liked this post. Do let me know your feedback on the animation and tutorial.

## Bình luận