Making of #つぶやきProcessing sketch (part 1)
The #つぶやきProcessing is Twitter hashtag used for indexing Processing (p5.js mostly) sketch code posted in a form of a tweet. The idea is to write code 280 characters long which creates a static or animated visual piece and to attach the result as an image or video respectively.
The #つぶやきProcessing topic requires a whole new article and I will probably cover it in one of the future posts. But for the time being, I suggest you check the hashtag and see all these beautiful pieces created by many talented artists and programmers.
What are we going to create?
In this tutorial, we’ll create a p5.js sketch, create a few visual variants, compress it, make 280 characters (or less) long code, and then leave it to you for further enhancements.
The only prerequisites you need are a text editor, a little JS knowledge, and a will to create a #つぶやきProcessing sketch.
Text editor
The fastest way to start coding #つぶやきProcessing sketch is to use p5js editor.
The editor is designed especially for p5.js sketches. It has integrated preview, syntax coloring, formatting tools, and many other useful options. It is small, fast and it costs nothing. The only thing you have to do is to register to use it.
For this tutorial it is enough to know these options:
- Play (run the code)
- Stop (stop playback of the code)
There is also the option to rename the sketch (3).
Let’s start
Select File > New in the editor menu, and you’ll get a basic sketch template:
function setup() {
createCanvas(400, 400);
}function draw() {
background(220);
}
Click Run to test it.
Beautiful!
The sketch
This is the result we are going to achieve:
The code
Most of the time simple and clean ideas result in simple code.
If you want to make a #つぶやきProcessing sketch, you must simplify your idea as much as possible. Always ask yourself what is the essence of the scene you want to make. Are all these objects necessary? Static or animated? Color or monochrome? Getting the balance between simplicity and visual richness is tough.
Code length limitation often kills enthusiasm and joy. Don’t worry. Limits boost creativity! You’ll return with a better solution later, tomorrow… or next month — it doesn’t matter when. And the feeling of accomplishment will be great!
This is the code that outputs the animation above:
function setup() {
createCanvas(400, 400, WEBGL);
noStroke();
}function draw() {
background(0);
pointLight(255, 255, 255, 0, -400, 400);
pointLight(200, 200, 200, 0, 0, 400);
for (let i = 0; i < TAU; i += PI / 256) {
push();
rotateZ(i);
translate(100, 0, 0);
rotateY(i + frameCount / 50);
box(30, 2, 30);
pop();
}
}
Copy & paste it into the p5.js editor and test.
The resulting scene has rich shading and relatively complex object. And yet the code is very simple.
Setup function
Our sketch is 400 pixels wide, and 400 pixels tall and it uses WEBGL renderer. These properties are set using createCanvas() function. They must be defined only once because creating canvas every frame is very slow and compute-intensive so we are putting the following code into the setup() function of the sketch. The setup() function executes only once — after a sketch starts.
function setup() {
createCanvas(400, 400, WEBGL);
noStroke();
}
By default, the edges of all objects are outlined with black lines. We don’t want these outlines. noStroke() disables drawing of them.
Draw function
Animation code goes into the draw() function. The draw() function executes 60 times each second which is perfect for animations. (the number of frames to be displayed every second is controlled with the frameRate() function)
Let’s deconstruct our draw() function.
function draw() {
background(0);
pointLight(255, 255, 255, 0, -400, 400);
pointLight(200, 200, 200, 0, 0, 400);
for (let i = 0; i < TAU; i += PI / 256) {
push();
rotateZ(i);
translate(100, 0, 0);
rotateY(i + frameCount / 50);
box(30, 2, 30);
pop();
}
}
Our sketch has a black background(). This function refreshes the screen, clears everything from the previous draw cycle, and fills it with the desired color.
background(0);
Try to use the code without background() and you’ll get a picture of what it does.
There are two pointLight() lights positioned at coordinates which give good surface shading of our object.
pointLight(255, 255, 255, 0, -400, 400);
pointLight(200, 200, 200, 0, 0, 400);
The first three numbers are rgb color values:
pointLight(255, 255, 255, 0, -400, 400).
The last three numbers are xyz position values:
pointLight(255, 255, 255, 0, -400, 400).
Modeling by duplications
The twisted torus in this sketch doesn’t exist as a p5.js object. Custom geometry is also not an option because the final code can be huge. But we can go in the opposite direction and use the simplest p5.js 3d primitive!
A squashed box() object duplicated enough times to create an impression of a torus (and twisted for the final touch) can be represented through the following steps:
for (let i = 0; i < TAU; i += PI / 256) { // 4, 32, 256, ...// For 4 boxes use 2 instead of 256
// For 64 boxes use 32 instead of 256
// For 512 boxes leave 256 as it is now
// We are using TAU (2*PI) hence the number of duplicates / 2push();
rotateZ(i);
translate(100, 0, 0);
rotateY(i + frameCount / 50);
box(30, 2, 30);
pop();
}
As you can see, we used box() and turned it into a complex object in a few steps:
- for loop duplicates the box desired number of times.
- Each loop step starts by saving current global transformation values using the push() command. Every transformation from this point is local.
- rotateZ() rotate the box around the Z axis by step defined in for loop.
- translate() the box 100 units to the right (3d space placement is not represented in pixels. The unit value is relative).
- rotateY() the box around the Y-axis using the current for loop step with a fraction of the current frame value (frameCount). This part animates the twisting of the torus.
- Draw the box() on the screen. 30 units wide, 2 units tall, and 30 units deep.
- Finally, use pop() to restore the saved global transformation values for the next for step.
Success!
If you run the code, you should get the following result:
Your turn
Now, let’s add some tweaks to the code. This is the part where you can include your visual improvements. The following variants are just examples of where you can go from here.
If you change the box(30, 2, 30) part of the code with one of the following variants you can get some interesting visual results:
box(s=abs(sin(i*6))*30,2,s,30)
box(s=abs(sin(i*2))*30,2,s,30)
box(s=abs(atan(PI-i))*30,2,s,30)
Every line of code between push() and pop() can be tweaked. I encourage you to play and experiment.
#つぶやきProcessing sketch
We have a sketch. But do we have a #つぶやきProcessing sketch?
Let’s count characters:
354 characters are way more than 280, which is the current Twitter limit. This code must be compressed.
I’ll show you how…
…in the next part of this tutorial 😁
Cheers,
KT