Meet Blobby in p5.js
The piece you see above (actual link here), is coded in p5.js. This organic generative art piece is actually pretty easy to code.
I’m going to use this to provide a (fairly) gentle introduction to p5.js, introduce you to classes in Javascript, and while doing so, create an generative art piece that you can stare at for a while.
Basic setup of p5.js
We first go through the basic things that need to be in place for any p5.js sketch. First, we set things up in the function setup().
function setup() {
createCanvas(800, 800);
background(0,255);
// noLoop();
// frameRate(30);
}
Pretty self-explanatory. But let me run through each line.
- createCanvas(width, height) creates a canvas with the width and height specified. Everything we draw later is within this canvas.
- background(0,255) sets the background as black (0 equals the absence of light!), that is fully opaque (255 for fully opaque; 0 for fully transparent)
Then we start drawing in the function draw().
function draw() {
background(159,65,115,30);
}
The only thing we are drawing here is a background. We are using another representation for the background color here. Instead of just having shades of grey from 0 to 255 (which is what we did in background in the setup() function), we now use set the background color by setting the red, green, blue, transparency values (background(red, green,blue,transparency)) .
Before we go further in these two functions, let’s code our Organic class. This is the class which we will instantiate to create the blobby shapes.
function Organic(radius,xpos,ypos,roughness,angle,color){
this.radius = radius; //radius of blob
this.xpos = xpos; //x position of blob
this.ypos = ypos; // y position of blob
this.roughness = roughness; // magnitude of how much the circle is distorted
this.angle = angle; //how much to rotate the circle by
this.color = color; // color of the blob
this.show = function(change){
noStroke(); // no stroke for the circle
fill(this.color); //color to fill the blob
//we enclose things between push and pop so that all transformations within only affect items within
push();
translate(xpos, ypos); //move to xpos, ypos
rotate(this.angle+change); //rotate by this.angle+change
//begin a shape based on the vertex points below
beginShape();
//The lines below create our vertex points
var off = 0;
for (var i = 0; i < TWO_PI; i += 0.1) {
var offset = map(noise(off, change), 0, 1, -this.roughness, this.roughness);
var r = this.radius + offset;
var x = r * cos(i);
var y = r * sin(i);
vertex(x, y);
off += 0.1;
}
endShape(); //end and create the shape
pop();
}
}
The code above is pretty self-explanatory and each line has been commented in case you need to know what’s happening.
But just to bring your attention to 2–3 areas.
First, we use this to save all the attributes (e.g. radius) that are passed into the function. This just means that these are attributes of this class (I hope this does not confuse you :P).
Second, we use push() and pop() functions to enclose transformations that only affect items within the push() and pop() functions.
And beginShape() and endShape() are for us to begin, end and create a shape based on vertex points within the beginShape() and endShape() functions.
With this class in place, all we need to do now is to create a number of instances of the Organic class and save it in an array named organics.
// organic is used to store the list of instances of Organic objects that we will create
var organics = [];
// The variable change stores the rate of rotation and the y coordinate for noise later
var change, colorsPalette;
function setup() {
...
change = 0;
colorsPalette = [color(146, 167, 202,30),
color(186, 196, 219,30),
color(118, 135, 172,30),
color(76, 41, 81,30),
color(144, 62, 92,30),
color(178, 93, 119,30),
color(215, 118, 136,30),
color(246, 156, 164,30),];
for (var i=0;i<110;i++){
organics.push(new Organic(0.1+1*i,width/2,height/2,i*1,i*random(90),colorsPalette[floor(random(8))]));
}
...
}
And now we just loop through the organics array in the draw() function and display them on the screen.
function draw() {
background(159,65,115,30);
for(var i=0; i<organics.length;i++){
organics[i].show(change);
}
change+=0.01;
}
The draw function continually loops and refreshes the screen. What we do here is to increment change each time, which then changes the offset in the Organic class and gives us our blobby looking shape.
And that’s it.