Begin your 2023 with Genuary!
December 27, 2022 • 14 min read
ACM at CSUF welcomes Genurary 2023!
Welcome to your introductory Genuary 2023 codelab where you will learn how to use https://editor.p5js.org/ to generate artwork for Genuary 2023.
What is Genuary? ❄️
Genuary 2023's official website https://genuary.art/ defines Genuary as:
Genuary is an artificially generated month of time where we build code that makes beautiful things.
There is a unique prompt for each day in the month of January. All of these prompts encourage the practice of creative expression in programming.
In our club Discord server, members are encouraged to share their creations throughout the monthlong event: Genuary 2023.
What is this codelab about?
In this codelab, you will learn how to create your first generative artwork with https://editor.p5js.org/ for Genuary 2023.
Once you have completed this codelab, you will have created a generative artwork using the 10print algorithm.
- Set up https://editor.p5js.org for Genuary
- Create a 10print sketch
- Save the result as a GIF
Quickly, what is 10print?
10print is a generative algorithm that creates a pattern of lines.
Our algorithm will draw out the pattern of lines on a canvas from the top left corner to the bottom right corner.
The algorithm is based on the following rules:
- 50% of the time, draw a line from the top left corner to the bottom right corner.
- The other 50% of the time, draw a line from the bottom left corner to the top right corner.
Supplemental reading:
Set up https://editor.p5js.org/ for Genuary
Sign in
Sign in to https://editor.p5js.org/ with your GitHub account.
Create a new sketch
To create a new sketch from scratch, go to https://editor.p5js.org/ and click on File
> New
.
Save the sketch with whatever name you like, or use a pattern such as genuary-2023-01-01
.
In your sketch, you will see a setup()
function and a draw()
function.
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
}
Start by removing background()
from the draw()
function.
Also, add a stroke()
function to the setup()
function to set the color of the lines to white.
function setup() {
createCanvas(400, 400);
stroke(255);
}
Make globals for the sketch
Above setup()
, we will define global variables for the sketch.
let x = 0;
let y = 0;
let s = 10;
Draw a diagonal line
In the draw()
function, draw a diagonal line with line()
.
Press to reveal the code
function draw() {
line(x, y, x + s, y + s);
}
Run
Draw a second diagonal line
To draw a second diagonal line, we will need to change the value of x
by s
pixels in each frame to move the next diagonal line to the right.
Press to reveal the code
function draw() {
line(x, y, x + s, y + s);
x += s;
}
Run
Draw the second row of diagonal lines
To draw the second row of diagonal lines, we will need to change the value of y
by s
pixels each time x
reaches the end of the canvas to move the next diagonal line down. Do not forget to send x
back to 0
when x
reaches the end of the canvas.
Press to reveal the code
function draw() {
line(x, y, x + s, y + s);
x += s;
if (x >= width) {
x = 0;
y += s;
}
}
Run
How many frames does it take to draw the entire canvas?
Since we know the width
and height
of the canvas, we can calculate the number of frames it takes to fill the canvas with one diagonal line per frame.
To do this, we will need to know the number of squares that fit horizontally and vertically on the canvas.
- width / s = number of squares that fit horizontally
- height / s = number of squares that fit vertically
We can then multiply the number of squares that fit horizontally by the number of squares that fit vertically to get the total number of squares.
(width / s) * (height / s) = total number of squares
Press to reveal the answer
Assuming you are drawing one diagonal line per frame, we can then calculate the number of frames it takes to fill the canvas given that the canvas is 400
pixels by 400
pixels and each square is 10
pixels by 10
pixels.
(400 / 10) * (400 / 10) = 1600 frames
Keep in mind how to get the number of frames it takes to fill the canvas in order to create a GIF later.
Randomize the direction of the diagonal line
To randomize the direction of the diagonal line, we can use random()
to generate a random number between 0
and 1
.
We can tell our program to draw a line from the top left corner to the bottom right corner if the random number is greater than 0.5
, and to draw a line from the bottom left corner to the top right corner of the random number is less than 0.5
.
Press to reveal the code
function draw() {
if (random() > 0.5) {
line(x, y, x + s, y + s);
} else {
line(x + s, y, x, y + s);
}
x += s;
if (x >= width) {
x = 0;
y += s;
}
}
Run
Draw infinitely
To start the animation over when it reaches the end of the canvas, we can set the y
value back to 0
when y
reaches the end of the canvas and clear()
the canvas.
Press to reveal the code
function draw() {
if (y >= height) {
y = 0;
clear();
}
if (random() > 0.5) {
line(x, y, x + s, y + s);
} else {
line(x + s, y, x, y + s);
}
x += s;
if (x >= width) {
x = 0;
y += s;
}
}
Save the animation as a GIF
Use saveGif()
to save the animation as a GIF.
Hint: Review saveGif()
short on YouTube.
Press to reveal the code
Allocate a boolean variable filming
to keep track of whether the animation is being recorded to GIF.
let x = 0;
let y = 0;
let s = 10;
let filming = false;
Set filming
to false
when the animation completes.
function draw() {
if (y >= height) {
filming = false;
y = 0;
clear();
}
if (random() > 0.5) {
line(x, y, x + s, y + s);
} else {
line(x + s, y, x, y + s);
}
x += s;
if (x >= width) {
x = 0;
y += s;
}
}
Make your call to saveGif()
in the mouseClicked()
function. When the mouse is pressed, the animation will be restarted and recorded to GIF.
Feel free to change the name of the GIF, but make sure the number of frames is the same as the number of frames it takes to fill the canvas.
function mousePressed() {
if (!filming) {
saveGif(
"genuary-2023-01-01.gif",
(width / s) * (height / s),
{ units: "frames", delay: 0 },
);
x = 0;
y = 0;
clear();
filming = true;
}
}
Run
Congratulations!
You have created your first animation for Genuary 2023 which concludes this
codelab!
Press to reveal the completed codelab
let x = 0;
let y = 0;
let s = 10;
let filming = false;
function setup() {
createCanvas(400, 400);
stroke(255);
}
function draw() {
if (y >= height) {
filming = false;
y = 0;
clear();
}
if (random() > 0.5) {
line(x, y, x + s, y + s);
} else {
line(x + s, y, x, y + s);
}
x += s;
if (x >= width) {
x = 0;
y += s;
}
}
function mousePressed() {
if (!filming) {
saveGif(
"genuary-2023-01-01.gif",
(width / s) * (height / s),
{ units: "frames", delay: 0 },
);
x = 0;
y = 0;
clear();
filming = true;
}
}
Next steps
Feel free to add more features to your animation, such as:
- Randomize the color of the diagonal line.
- Change the size of the diagonal line.
- Customize the way in which the diagonal lines are drawn.
If you are interested in learning more about p5.js, check out the following references:
More on saveGif()
It is no coincidence that this codelab features the saveGif()
API. The first prompt of Genuary 2023 is "Perfect loop / Infinite loop / endless GIFs". The saveGif()
API provided by p5.js is a powerful tool that happens to help with Genuary 2023 day 1 in particular, and even with other prompts later this month at the artist's discretion.
Social media
You are encouraged to share your GIF on your favorite social media and tag it with #genuary and #genuary2023 and also #genuary1, #genuary2, etc, depending on which prompt you are working on.
Do not forget to send your GIF to the associated thread on our club Discord server, https://acmcsuf.com/discord!