Date: 2026-09-14
Harold Cohen - The Age of Intelligent Machines - 1987 (Clip)
Harold Cohen - Collaborations with my Other Self - 2011 (Interview)
You know how to use variables, create functions, use if statements, create animations, get user input, and use for loops. This tutorial introduces arrays (ordered tables in Lua), which let you store multiple values in a single variable!
Let’s say you want to draw multiple circles that bounce around the screen. You might start with code like this:
require("L5")
circle1X = 100
circle1Y = 100
circle1SpeedX = 2
circle1SpeedY = 1
circle2X = 200
circle2Y = 150
circle2SpeedX = -1
circle2SpeedY = 2
circle3X = 150
circle3Y = 200
circle3SpeedX = 1
circle3SpeedY = -2
function setup()
size(300, 300)
end
function draw()
background(220)
-- Move and draw circle 1
circle1X = circle1X + circle1SpeedX
circle1Y = circle1Y + circle1SpeedY
if circle1X < 0 or circle1X > width then circle1SpeedX = circle1SpeedX * -1 end
if circle1Y < 0 or circle1Y > height then circle1SpeedY = circle1SpeedY * -1 end
circle(circle1X, circle1Y, 20)
-- Move and draw circle 2
circle2X = circle2X + circle2SpeedX
circle2Y = circle2Y + circle2SpeedY
if circle2X < 0 or circle2X > width then circle2SpeedX = circle2SpeedX * -1 end
if circle2Y < 0 or circle2Y > height then circle2SpeedY = circle2SpeedY * -1 end
circle(circle2X, circle2Y, 20)
-- Move and draw circle 3
circle3X = circle3X + circle3SpeedX
circle3Y = circle3Y + circle3SpeedY
if circle3X < 0 or circle3X > width then circle3SpeedX = circle3SpeedX * -1 end
if circle3Y < 0 or circle3Y > height then circle3SpeedY = circle3SpeedY * -1 end
circle(circle3X, circle3Y, 20)
endThis is very repetitive! And what if you wanted 10 circles? Or 100?
An array is an ordered table in Lua - a table that holds multiple values in a specific sequence.
To create an ordered table in Lua, use curly brackets
{}:
circleX = {100, 200, 150}This creates a table named circleX that
holds three values: 100, 200, and
150.
To access an element in a table, use square brackets
[] with an index:
print(circleX[1]) -- prints 100
print(circleX[2]) -- prints 200
print(circleX[3]) -- prints 150Important: In Lua, arrays start at index
1, not 0!
Arrays become powerful when combined with for loops. Instead of writing repetitive code for each circle, you can use a loop:
require("L5")
circleX = {100, 200, 150}
circleY = {100, 150, 200}
circleSpeedX = {2, -1, 1}
circleSpeedY = {1, 2, -2}
function setup()
size(300, 300)
end
function draw()
background(220)
for i = 1, 3 do
-- Move circle
circleX[i] = circleX[i] + circleSpeedX[i]
circleY[i] = circleY[i] + circleSpeedY[i]
-- Bounce off edges
if circleX[i] < 0 or circleX[i] > width then
circleSpeedX[i] = circleSpeedX[i] * -1
end
if circleY[i] < 0 or circleY[i] > height then
circleSpeedY[i] = circleSpeedY[i] * -1
end
-- Draw circle
circle(circleX[i], circleY[i], 20)
end
endNow the code is much shorter and easier to work with!
Instead of hardcoding the number of elements, you can use
the # operator to get the length of a
table:
for i = 1, #circleX do
-- code here
endThis makes it easy to add or remove elements without changing your loop!
You can add elements to a table using
table.insert(). This takes two arguments: the
name of the table, and the item you want to insert at the
end:
table.insert(tableName, value) -- adds to endOptionally, you can specify an index as the second argument to insert the new element at a specific position in the table:
table.insert(tableName, index, value) -- inserts at specific positionHere’s an example:
require("L5")
circleX = {}
circleY = {}
function setup()
size(300, 300)
background(220)
end
function draw()
-- Don't clear background - leave a trail
end
function mousePressed()
table.insert(circleX, mouseX)
table.insert(circleY, mouseY)
-- Draw all circles
for i = 1, #circleX do
circle(circleX[i], circleY[i], 30)
end
endThis program adds a circle wherever you click!
You can remove elements using
table.remove(). This works similarly to
table.insert() - you pass it the table name,
and optionally an index:
table.remove(tableName) -- removes last element
table.remove(tableName, index) -- removes element at specific positionIf you don’t specify an index, it removes the last element. If you do specify an index, it removes the element at that position.
Here’s an example:
require("L5")
circleX = {}
circleY = {}
function setup()
size(300, 300)
end
function draw()
background(220)
-- Draw all circles
for i = 1, #circleX do
circle(circleX[i], circleY[i], 30)
end
end
function mousePressed()
-- Add circle at mouse position
table.insert(circleX, mouseX)
table.insert(circleY, mouseY)
end
function keyPressed()
-- Remove last circle when any key is pressed
if #circleX > 0 then
table.remove(circleX)
table.remove(circleY)
end
endClick to add circles, press any key to remove the last one!
You can use loops to fill arrays with random values:
require("L5")
circleX = {}
circleY = {}
circleSize = {}
function setup()
size(300, 300)
-- Create 10 random circles
for i = 1, 10 do
circleX[i] = random(width)
circleY[i] = random(height)
circleSize[i] = random(10, 50)
end
end
function draw()
background(220)
-- Draw all circles
for i = 1, #circleX do
circle(circleX[i], circleY[i], circleSize[i])
end
endThis creates 10 circles at random positions with random sizes!
You can create tables of tables (2D arrays) for grid-based data:
require("L5")
grid = {}
function setup()
size(300, 300)
-- Create a 10x10 grid
for row = 1, 10 do
grid[row] = {}
for col = 1, 10 do
grid[row][col] = random(255)
end
end
end
function draw()
for row = 1, 10 do
for col = 1, 10 do
fill(grid[row][col])
rect((col - 1) * 30, (row - 1) * 30, 30, 30)
end
end
endThis creates a grid of randomly colored squares!
Here’s a complete example that creates a trail that follows the mouse:
require("L5")
trailX = {}
trailY = {}
maxLength = 20
function setup()
size(300, 300)
end
function draw()
background(220)
-- Add current mouse position
table.insert(trailX, mouseX)
table.insert(trailY, mouseY)
-- Remove oldest position if trail is too long
if #trailX > maxLength then
table.remove(trailX, 1)
table.remove(trailY, 1)
end
-- Draw trail
for i = 1, #trailX do
size = (i / #trailX) * 30
circle(trailX[i], trailY[i], size)
end
endThis creates a trail that follows your mouse, with circles getting bigger toward the mouse.
Getting started with strudel: There are many different sounds loaded into strudel by default; listed below are the ones I find myself using most frequently, however we can introduce more sounds later.
Since we’re just getting started, we’re going to focus on the drum sounds only while introducing the syntax for making sound in Strudel:
sound("bd rim bd cp") here is a sequence
using some of the drums we learned before, feel free to
paste this into Strudel to
listen to it!sound("bd rim bd cp").bank("akaimpc60")s("[rim bd] [rim <bd oh>] bd bd bd ~").bank("tr707")s("[rim bd] [rim <bd oh>] bd!3 ~").bank("tr707") //bd!3 plays the bass drum 3 timess("rim hh rim bd*2") //plays bd twice in the same section of the sequence, as if using a subsequences("rim hh rim bd!2") //acts as if bd was placed twice in the sequence_$: s("[rim bd] [rim <bd oh>]").bank("tr707") //this line isnt playing
//$: s("~ sd").fast(2) //neither is this one
$: s("rim hh rim bd!5") //but this line is!
Activity: make drum loop with dice! 4 dice will be handed out and we will make a loop with these restrictions determined by the results
setcpm(result*10+80/4)MAKING MELODIES - Using the note() function allows you to write melodies using different sounds, it’s useful for using synth sounds like the ones on the first page - Notes can be written out in an a-g scale like when using a piano roll tool in a different program, in the format of the note you want along with the octave
$: note("[e4 d4]!2 [a3 <c4 ~>]!2").s("tri")
$: note("<e3 d3 a2!2>!3").s("sine").swing(2)

Lesson by Jaiden Kelly, licensed under
CC
BY-ND
4.0
Contains material adapted from Arrays (ordered tables) by L5lua, Arrays by Happy Coding, licensed under CC BY 4.0