# Learn How to Make Generative Art: From Zero to random()

Earlier this month, I stumbled upon the #generativeart hashtag as I was scrolling through Instagram. I found several interesting geometric and abstract pieces, each with its own unique visual style. As someone who loves to combine computer science and visual arts, I wanted to join the fun. So, over the past month, I challenged myself to learn the basics of generative art.

## What is generative art?

Generative art, also known as procedural art or algorithmic art, is a form of artwork that autonomously creates itself. This can take the form of mathematical functions, as is the case in Mandelbrot’s Fractal. Other times, randomness takes the wheel and creates chaotic artwork that Jackson Pollock would be proud of. In many cases, artists utilize a combination of both.

## Let’s make some art!

There are many tools available for making generative art, including Processing, p5.js (a JS implementation of Processing), and Turtle graphics. All of these tools offer similar functionality, so choose the one you’re most comfortable with. I decided to use the Python implementation of Turtle.

Let’s write a program to generate a grid of diagonal lines, using randomness to decide whether the lines slant left or right.

First off, let’s define some constants: `CANVAS_SIZE`, which will determine the width and height of the canvas, and `DENSITY`, which will determine the number of rows and columns in the grid.

``````
CANVAS_SIZE = 500
DENSITY = 12
``````

Next, we’ll import the `turtle` module and do some initial setup.

``````
import turtle
t = turtle.Turtle()
s = turtle.Screen()
s.setup(CANVAS_SIZE, CANVAS_SIZE)
``````

Now we get to the fun part. We’ll set up a nested loop to iterate through all the rows and columns in the grid and stub out a `draw_line` function that will draw a line at the specified row and column.

``````
t.penup()
def draw_line(row, col):
pass
for row in range(DENSITY):
for col in range(DENSITY):
draw_line(row, col)
``````

In our first iteration, we’ll try drawing all lines slanted to the right. With a bit of math, we can calculate the lower-left and upper-right coordinates of each grid cell.

``````
def draw_line(row, col):
lower_left = (
(col * CANVAS_SIZE / DENSITY) - CANVAS_SIZE / 2,
(row * CANVAS_SIZE / DENSITY) - CANVAS_SIZE / 2
)
upper_right = (
((col + 1) * CANVAS_SIZE / DENSITY) - CANVAS_SIZE / 2,
((row + 1) * CANVAS_SIZE / DENSITY) - CANVAS_SIZE / 2
)
t.goto(lower_left)
t.pendown()
t.goto(upper_right)
t.penup()
``````

If we run the program at this point, we get the following output:

It works! But it’s not too exciting. Let’s add some randomness into the mix. We’ll import the `random` module and use its `randint` function to generate either 0 or 1. Based on the result, we’ll either draw a left-slanted line or a right-slanted line.

``````
import random
def draw_line(row, col):
lower_left = (
(col * CANVAS_SIZE / DENSITY) - CANVAS_SIZE / 2,
(row * CANVAS_SIZE / DENSITY) - CANVAS_SIZE / 2
)
upper_right = (
((col + 1) * CANVAS_SIZE / DENSITY) - CANVAS_SIZE / 2,
((row + 1) * CANVAS_SIZE / DENSITY) - CANVAS_SIZE / 2
)
lower_right = (
((col + 1) * CANVAS_SIZE / DENSITY) - CANVAS_SIZE / 2,
(row * CANVAS_SIZE / DENSITY) - CANVAS_SIZE / 2
)
upper_left = (
(col * CANVAS_SIZE / DENSITY) - CANVAS_SIZE / 2,
((row + 1) * CANVAS_SIZE / DENSITY) - CANVAS_SIZE / 2
)
res = random.randint(0, 1)
if res == 0:
t.goto(upper_left)
t.pendown()
t.goto(lower_right)
t.penup()
else:
t.goto(lower_left)
t.pendown()
t.goto(upper_right)
t.penup()
``````

When we run the program now, we end up with this cool geometric pattern that’s different each time you run it: