From Syntax to Symmetry: A Journey into Generative Art with p5.js — I
Generative art, also known as algorithmic art, refers to artworks that are partially or entirely created through non-human or autonomous systems. While generative art isn’t limited to programming alone, in this post, we’ll explore how to create artwork using just code — specifically through a JavaScript library called p5.js.
Most people associate programming with automating tasks, building applications, or competing in coding challenges. But have you ever wondered if there’s a fun, creative, and artistic side to coding?
That’s exactly the side we’ll be diving into here — creative coding. It’s all about using your coding skills to create art or cool digital experiences, not just practical things like apps or websites. Think of it as coding for expression, exploration, and play.
As a first step into this world, we’ll start by creating some geometric and abstract patterns — purely through code. And just like every artist needs a canvas, every programmer needs an editor. Luckily, p5.js provides a web-based editor that’s perfect for getting started. If you prefer, you can also set it up in VS Code.
The image above shows the default screen in the p5.js editor. You’ll be writing your main code in the sketch.js file, and when you click the Run button in the top-left corner, the output will appear in the preview window. As always, the console window is your debugging buddy—use it to catch any errors or log values while experimenting.
Before jumping into writing programs, it might be helpful to skim through the official p5.js documentation. It’s well-organized and super beginner-friendly! Okay, so… ready to paint your canvas?
p5.js relies on two main functions: setup() and draw().
- The setup() function runs once when the program starts. You typically define initial settings here—like canvas size, background color, and other static values.
- The draw() function runs continuously , from top to bottom, by default 60 times per second (this is known as the frame rate ).
Since we’re going to be creating static patterns , we can skip the draw() function for now. So, how do we go about designing these patterns?
Let’s start simple — with just some squares displayed on the screen, like this:
function setup() {
createCanvas(500,500);
fill(255, 0, 0);
let space = 50;
for (x=0;x<width+50;x+=space){
for (y=0;y<height+50;y+=space){
square(x,y,10)
square(x+space/2,y+space/2,10)
}
}
}
Now, let’s try to understand the code a bit.
The createCanvas() function takes two parameters: the width and height of the canvas. In this case, it's 500x500, which means we'll be drawing on a square area that's 500 pixels wide and 500 pixels tall.
Next, we use the fill() function to define the color that will be used to fill all the shapes. fill(0) sets the color to black and fill(255,0,0) as in our case sets it to red.
We then create a variable called space, which defines the amount of space between each square. Here, it's set to 50 pixels.
Finally, we use two nested loops to span the entire canvas — one loop for the x-axis and one for the y-axis — each incrementing by the value of space. In each iteration, two squares are drawn:
One at (x, y) with a side length of 10, and another slightly offset at (x + space / 2, y + space / 2)—which places it 25 pixels diagonally from the first.This alternating placement gives the pattern a nice, staggered grid effect.
So, that was fun. Let’s take it up a notch and add some lines to our pattern to get something like this:
Let’s try to understand what has happened here. We have lines that run horizontally and vertically through the main squares. To achieve this, we just need to tweak the code a bit.
function setup() {
createCanvas(502,502);
fill(255, 0, 0);
rectMode(CENTER);
let space = 50;
for (x=0;x<width;x+=space){
for (y=0;y<height;y+=space){
line(x,y,x+space,y);
line(x,y,x,y+space);
square(x,y,10)
square(x+space/2,y+space/2,10)
}
}
}
We’ve made only a few changes here:
1.First off, rectMode(CENTER) ensures that the squares (and the lines passing through them) are centered at the given (x, y) coordinates, rather than starting from the top-left corner.
- Apart from that, inside the loop, we’ve added two line() calls. The line() function takes four parameters: the first two specify the start coordinates, and the next two specify the end coordinates.
In addition to the basic patterns we’ve explored, p5.js also allows us to create much more intricate and visually stunning designs. From complex geometric shapes to organic, flowing patterns, the possibilities are endless. Below are a few examples of patterns that can be made using p5.js, showcasing the versatility and creativity that can be achieved. These patterns range from mesmerizing fractals to dynamic, interactive visuals, giving you a glimpse of what we can dive deeper into in future posts. The images below are made completely out of p5.js.
This was a fun and simple start to exploring p5.js! The patterns we created are just the tip of the iceberg. There’s so much more to discover, from interactive visuals to complex animations. Stay tuned for upcoming posts where we’ll continue to dive deeper into the exciting world of p5.js and create even more fascinating projects together!