I built one of my favourite visual hello world in Norns

```
-- graph
--
-- graph sketch
-- key 2 adds node
-- key 3 removes node
-- enc 3 controls draw distance
--
local nodes = {}
local thresh = 30
function init()
nodes = {
_random_node(),
_random_node(),
_random_node(),
}
end
function key(n,z)
if n == 2 and z == 1 then
-- add node
table.insert(nodes, _random_node())
end
if n == 3 and z == 1 and #nodes > 0 then
table.remove(nodes,1)
end
end
function enc(n,d)
if n==3 then
-- clamp number of notes from 1 to 4
thresh = math.min(128,(math.max(thresh + d,1)))
end
redraw()
end
function run()
for i=1, #nodes do
velocity = nodes[i].velocity
nodes[i].location[1] = nodes[i].location[1] + velocity[1]
nodes[i].location[2] = nodes[i].location[2] + velocity[2]
x = nodes[i].location[1]
y = nodes[i].location[2]
if (x < 0 or x > 128) then
nodes[i].velocity[1] = nodes[i].velocity[1] * -1
end
if (y < 0 or y > 64) then
nodes[i].velocity[2] = nodes[i].velocity[2] * -1
end
end
end
function redraw()
screen.clear()
screen.level(7)
screen.aa(1)
screen.line_width(1)
for i=1, #nodes do
-- draw
for j=i, #nodes do
x1 = nodes[i].location[1]
y1 = nodes[i].location[2]
x2 = nodes[j].location[1]
y2 = nodes[j].location[2]
if (_len(x1,y1,x2,y1) < thresh) then
_line(x1,y1,x2,y2)
end
end
end
screen.update()
end
function update(sec)
run()
redraw()
end
function _random_node()
return {
location={math.random(128), math.random(64)},
velocity={math.random(4) - 2, math.random(4) - 2}
}
end
function _line(x1,y1,x2,y2)
screen.move(x1,y1)
screen.line(x2,y2)
screen.close()
screen.stroke()
end
function _len(x1,y1,x2,y2)
return math.sqrt(
math.pow(x2 - x1 ,2) +
math.pow(y2 - y1 ,2)
)
end
-- Interval
re = metro.init()
re.time = 1.0 / 15
re.event = function()
update()
end
re:start()
```