Skip to content

Commit cf0bd63

Browse files
committed
add computational-poetry tutorial starter
1 parent df87560 commit cf0bd63

1 file changed

Lines changed: 374 additions & 0 deletions

File tree

Lines changed: 374 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,374 @@
1+
# Computational Poetry with L5
2+
3+
## Overview
4+
5+
In this tutorial, you'll learn how to create generative visual poetry using L5, a creative coding library based on p5.js and Processing, but written in Lua. We'll explore how code can arrange words and images to create dynamic compositions that change with every interaction.
6+
7+
**Time Required:** 60 minutes
8+
9+
**Prerequisites:** Previous knowledge working with p5.js or Processing is recommended.
10+
11+
## Learning Objectives
12+
13+
By the end of this tutorial, students will be able to:
14+
15+
- Understand the basics of L5 and how it relates to p5.js/Processing
16+
- Draw text and shapes to the screen using code
17+
- Create and manipulate arrays of strings
18+
- Use randomness to create generative compositions
19+
- Build a grid-based layout system
20+
- Combine text, randomness, and interaction to create computational poetry
21+
22+
## Setup
23+
24+
To get started with L5, you'll need to set it up on your computer:
25+
26+
- **Mac users:** [L5 Setup for Mac](https://l5lua.org/download/install-mac)
27+
- **Windows users:** [L5 Setup for Windows](https://l5lua.org/download/install-windows)
28+
29+
Once you have L5 installed, you're ready to begin.
30+
31+
## What is L5?
32+
33+
L5 is a creative coding library that brings the simplicity and approachability of p5.js and Processing to the Lua programming language. If you've used p5.js or Processing before, you'll find L5 familiar - it uses the same basic structure with `setup()` and `draw()` functions, and similar function names for drawing shapes, working with color, and handling interaction.
34+
35+
The main difference is that L5 uses Lua syntax, which is known for being clean and beginner-friendly. Lua uses simple keywords like `function`, `end`, and `for` that make code easy to read.
36+
37+
## Getting Started: Your First L5 Sketch
38+
39+
Every L5 sketch starts with requiring the library. Create a new file and type:
40+
41+
```lua
42+
require 'L5'
43+
44+
function setup()
45+
-- Your setup code goes here
46+
end
47+
```
48+
49+
The `setup()` function runs once when your program starts. This is where we'll put code that only needs to happen at the beginning.
50+
51+
## Step 1: Drawing a Background
52+
53+
Let's start by setting a background color. Add this inside your `setup()` function:
54+
55+
```lua
56+
require 'L5'
57+
58+
function setup()
59+
background('white')
60+
end
61+
```
62+
63+
Run your sketch. You should see a white canvas. Try changing `'white'` to other colors like `'lightblue'`, `'pink'`, or `'lavender'`. You can use any of the [HTML Color Names](https://www.w3schools.com/colors/colors_names.asp), or RGB numbers like `background(255, 0, 255)` or hexadecimal: `background('#7FFFD4')`.
64+
65+
## Step 2: Drawing Basic Shapes
66+
67+
L5 can draw shapes just like p5.js. Let's add a circle:
68+
69+
```lua
70+
require 'L5'
71+
72+
function setup()
73+
background('white')
74+
fill('black')
75+
circle(100, 100, 50)
76+
end
77+
```
78+
79+
The `fill()` function sets the color for shapes, and `circle(x, y, diameter)` draws a circle at position (100, 100) with a diameter of 50 pixels.
80+
81+
Try drawing other shapes:
82+
- `rect(x, y, width, height)` - draws a rectangle
83+
- `ellipse(x, y, width, height)` - draws an ellipse
84+
- `line(x1, y1, x2, y2)` - draws a line
85+
86+
## Step 3: Drawing Text on Screen
87+
88+
Now let's draw some text instead of shapes:
89+
90+
```lua
91+
require 'L5'
92+
93+
function setup()
94+
background('white')
95+
fill('black')
96+
textSize(32)
97+
text('hello', 100, 100)
98+
end
99+
```
100+
101+
The `text()` function draws text at a specific position. The first parameter is the string to display, and the next two are the x and y coordinates.
102+
103+
Try changing:
104+
- The word in quotes
105+
- The numbers (position)
106+
- The `textSize()` value
107+
- Add `textAlign(CENTER, CENTER)` before the text to change alignment
108+
109+
## Step 4: Creating an Array of Strings
110+
111+
Instead of just one word, let's create a collection of words we can choose from. In Lua, we use curly braces `{}` to create arrays (called "tables" in Lua):
112+
113+
```lua
114+
require 'L5'
115+
116+
words = {"eye", "nose", "mouth", "ear", "brain"}
117+
118+
function setup()
119+
background('white')
120+
fill('black')
121+
textSize(32)
122+
text(words[1], 100, 100)
123+
end
124+
```
125+
126+
The array `words` holds multiple strings. We can access them using square brackets with a number. **Important:** Lua arrays start at index 1, not 0!
127+
128+
Try displaying different words by changing `words[1]` to `words[2]`, `words[3]`, etc.
129+
130+
## Step 5: Picking a Random String
131+
132+
Instead of always showing the same word, let's pick one randomly:
133+
134+
```lua
135+
require 'L5'
136+
137+
words = {"eye", "nose", "mouth", "ear", "brain"}
138+
139+
function setup()
140+
background('white')
141+
fill('black')
142+
textSize(32)
143+
text(random(words), 100, 100)
144+
end
145+
```
146+
147+
The `random()` function can pick a random item from an array when you pass it an array. Run your sketch multiple times - you should see different words!
148+
149+
## Step 6: Creating a Grid
150+
151+
Now we'll use loops to create a grid of positions where words could appear. We'll use two variables to control the grid spacing:
152+
153+
```lua
154+
require 'L5'
155+
156+
words = {"eye", "nose", "mouth", "ear", "brain"}
157+
158+
function setup()
159+
background('white')
160+
blockW = width/10
161+
blockH = height/10
162+
163+
fill('black')
164+
textSize(24)
165+
166+
for y=1,height,blockH do
167+
for x=1,width,blockW do
168+
text(random(words), x, y)
169+
end
170+
end
171+
end
172+
```
173+
174+
Let's break down the loop:
175+
176+
- `for y=1,height,blockH do` means "start at 1, go up to the canvas height, increasing by blockH each time"
177+
- The nested loop does the same for x
178+
- `width` and `height` are built-in variables that give you the canvas dimensions
179+
180+
This creates a grid of words across your entire canvas.
181+
182+
## Step 7: Randomly Showing or Hiding Words
183+
184+
Right now we're showing a word at every grid position. Let's make it more interesting by only sometimes showing a word:
185+
186+
```lua
187+
require 'L5'
188+
189+
words = {"eye", "nose", "mouth", "ear", "brain", "arm", "leg", "head", "foot"}
190+
191+
function setup()
192+
background('white')
193+
blockW = width/10
194+
blockH = height/10
195+
196+
fill('black')
197+
textAlign(RIGHT, BOTTOM)
198+
textSize(24)
199+
200+
for y=1,height,blockH do
201+
for x=1,width,blockW do
202+
if random() > 0.9 then
203+
text(random(words), x, y)
204+
end
205+
end
206+
end
207+
end
208+
```
209+
210+
The `if random() > 0.9 then` line checks if a random number (between 0 and 1) is greater than 0.9. This means only about 10% of the grid positions will show a word.
211+
212+
Try changing `0.9` to different values:
213+
- `0.5` = 50% of positions show words
214+
- `0.7` = 30% of positions show words
215+
- `0.95` = only 5% of positions show words
216+
217+
## Step 8: Adding Interaction
218+
219+
Let's make it so clicking the mouse regenerates the composition:
220+
221+
```lua
222+
require 'L5'
223+
224+
words = {"eye", "nose", "mouth", "ear", "brain", "arm", "leg", "head", "foot"}
225+
226+
function setup()
227+
background('white')
228+
blockW = width/10
229+
blockH = height/10
230+
231+
fill('black')
232+
textAlign(RIGHT, BOTTOM)
233+
textSize(24)
234+
235+
for y=1,height,blockH do
236+
for x=1,width,blockW do
237+
if random() > 0.9 then
238+
text(random(words), x, y)
239+
end
240+
end
241+
end
242+
end
243+
244+
function mousePressed()
245+
setup()
246+
end
247+
```
248+
249+
The `mousePressed()` function runs whenever you click the mouse. By calling `setup()` again, we redraw everything with new random positions!
250+
251+
## Making It Your Own
252+
253+
Now that you have the basic structure, try customizing it:
254+
255+
1. **Change the words:** Replace the body parts with your own theme
256+
- Emotions: "joy", "anger", "fear", "sadness"
257+
- Colors: "crimson", "azure", "golden", "silver"
258+
- Use words from a poem you wrote
259+
260+
2. **Adjust the density:** Change the `0.9` value to make it more or less crowded
261+
262+
3. **Experiment with text alignment:** Try `LEFT`, `RIGHT`, `CENTER` for horizontal and `TOP`, `CENTER`, `BOTTOM` for vertical
263+
264+
4. **Change the grid:** Make `blockW` and `blockH` smaller for a finer grid, or larger for bigger gaps
265+
266+
5. **Add color:** Try `fill('red')` or use RGB values like `fill(255, 0, 0)`
267+
268+
## Extension Ideas
269+
270+
Ready to go further? Try these challenges:
271+
272+
### Adding Animation
273+
274+
Instead of only drawing in `setup()`, you can use the `draw()` function to create continuous animation:
275+
276+
```lua
277+
function draw()
278+
background('white')
279+
-- your grid code here
280+
end
281+
```
282+
283+
This will create a constantly changing composition!
284+
285+
### Using Mouse Interaction
286+
287+
Make your composition respond to the mouse position:
288+
289+
```lua
290+
textSize(mouseX / 10) -- Text size changes with mouse X position
291+
```
292+
293+
This can cause freezing if mouseX is 0 at the beginning of the sketch, so we can constrain it to have a minimum value.
294+
295+
```lua
296+
textSize(constrain(mouseX,10,width) / 10)
297+
```
298+
299+
Now the size will change but never get smaller than 10.
300+
301+
Or only show words near the mouse:
302+
303+
```lua
304+
if dist(x, y, mouseX, mouseY) < 100 then
305+
text(random(words), x, y)
306+
end
307+
```
308+
309+
### Adding Images
310+
311+
L5 can also work with images. First, load an image in `setup()`:
312+
313+
```lua
314+
img = loadImage('path/to/your/image.jpg')
315+
```
316+
317+
Then draw it in your grid instead of (or alongside) text:
318+
319+
```lua
320+
if random() > 0.9 then
321+
if random() > 0.5 then
322+
text(random(words), x, y)
323+
else
324+
image(img, x, y, 50, 50)
325+
end
326+
end
327+
```
328+
329+
### Rotating Text
330+
331+
Add rotation to make text appear at different angles:
332+
333+
```lua
334+
push()
335+
translate(x, y)
336+
rotate(random() * TWO_PI)
337+
text(random(words), 0, 0)
338+
pop()
339+
```
340+
341+
## Vocabulary
342+
343+
- **Generative:** Art or designs created by following a set of rules or algorithms, often involving randomness
344+
- **Computational Poetry:** Using code and algorithms to create, arrange, or manipulate text as a form of poetic expression
345+
- **Array/Table:** A collection of values stored together (in Lua, called a "table")
346+
- **Algorithm:** A set of step-by-step instructions to solve a problem or create something
347+
- **Parameter:** A value you pass into a function to customize how it works
348+
- **Random:** Unpredictable; choosing something without a pattern
349+
- **Grid:** A layout system based on evenly-spaced rows and columns
350+
- **Iteration:** Repeating a process multiple times (like in a loop)
351+
352+
## Going Further
353+
354+
Computational poetry is a rich field with many approaches. Research these artists and techniques:
355+
356+
- **Concrete poetry:** Poetry where the visual arrangement is as important as the words
357+
- **Blackout poetry:** Creating new poems by selectively revealing words from existing text
358+
- **Erasure poetry:** Similar to blackout poetry, removing words to create new meaning
359+
- **Artists to explore:** Allison Parrish, Nick Montfort, Lillian-Yvonne Bertram
360+
- **Online computational poetry:** [Taper](https://taper.badquar.to/), [The HTML Review](https://thehtml.review), [Random Walk](https://randomwalk.club/)
361+
362+
## Resources
363+
364+
- [L5 Documentation](https://l5lua.org/reference)
365+
- [More L5 Tutorials](https://l5lua.org/tutorials)
366+
- [L5 Examples](https://l5lua.org/examples)
367+
368+
## Share Your Work!
369+
370+
Created something interesting? Share it with the [L5 category](https://discourse.processing.org/c/l5/29) on the Processing Discourse forum or with #L5 on social media. We'd love to see what you make.
371+
372+
---
373+
374+
*This tutorial was created for CCFest and is available under a Creative Commons Attribution 4.0 International License.*

0 commit comments

Comments
 (0)