# 6 useful snippets

I was inspired by the blog post 6 Useful Snippets – Naming Things and implemented in it Codea.

``````
--# Main
-- balls - inspired by https://blog.bruce-hill.com/6-useful-snippets
function setup()
viewer.mode = FULLSCREEN_NO_BUTTONS
W, H = WIDTH, HEIGHT
balls = {}
dragging = false
GRAVITY = vec2(0, -2000)
K = 0.5

for i = 0, 40 do
local ball = {
id=i,
pos=vec2(math.random()*W, math.random()*H),
color=hsl(360*((i*GOLDEN_RATIO) % 1), .5, .7, 1.)
}
ball.prevpos = ball.pos
table.insert(balls, ball)
end

-- rotating ball
stirrer = balls[1]
stirrer.color = color(255, 0, 225)
stir_angle = 0
ellipseMode(CENTER)
end

function draw()
background(40, 40, 50)
strokeWidth(1)

dt = DeltaTime

for i, b in ipairs(balls) do
local nextpos = ((b.pos * 2) - b.prevpos) + GRAVITY * dt*dt
b.prevpos = b.pos
b.pos = nextpos
end

stir_angle = stir_angle + dt*6.28/4
-- solve contraints
for i = 1, 5 do
if dragging then
dragging.pos = mix(dragging.pos, CurrentTouch.pos, .35)
end

if stirrer then
stirrer.pos = mix(stirrer.pos, vec2(W/2+H/3*math.cos(stir_angle), H/2+H/3*math.sin(stir_angle)), .35)
end

local collisions = collisions_between(balls)
for j, cs in ipairs(collisions) do
local a = cs[1];
local b = cs[2];
local a2b = (b.pos -a.pos):normalize()
a.pos = a.pos - (a2b * (K*needed_dist*(b.mass/(a.mass+b.mass))))
b.pos = b.pos + (a2b * (K*needed_dist*(a.mass/(a.mass+b.mass))))
end
end

for i, b in ipairs(balls) do
if clamped.x ~= b.pos.x or clamped.y ~= b.pos.y then
b.pos = mix(b.pos, clamped, K)
-- Damping:
b.prevpos = mix(b.prevpos, b.pos, .001)
end
end
end

for i, ball in ipairs(balls) do
fill(ball.color)
if ball == dragging then
strokeWidth(8)
else
strokeWidth(1)
end
end
end

function touched(touch)
if touch.state == BEGAN then
dragging = ball_at(touch.pos)
elseif touch.state == ENDED then
dragging = false
end
end

--# Utils
GOLDEN_RATIO = (math.sqrt(5) - 1)/2

function hsl(h, s, v, a)
local r, g, b

local i = math.floor(h * 6);
local f = h * 6 - i;
local p = v * (1 - s);
local q = v * (1 - f * s);
local t = v * (1 - (1 - f) * s);

i = i % 6

if i == 0 then r, g, b = v, t, p
elseif i == 1 then r, g, b = q, v, p
elseif i == 2 then r, g, b = p, v, t
elseif i == 3 then r, g, b = p, q, v
elseif i == 4 then r, g, b = t, p, v
elseif i == 5 then r, g, b = v, p, q
end

return color(r * 255, g * 255, b * 255, a * 255)
end

function mix(a, b, amount)
return (1-amount)*a + amount*b
end

function clamp(x, min, max)
if x < min then
return min
end
if x > max then
return max
end
return x
end

function collisions_between(things)
local S = collision_scale;
local buckets = {}
local collisions = {}
for i, t in ipairs(things) do
local collided = {}
local key = x .. "," .. y;
if buckets[key] == nil then
buckets[key] = {}
end
for j, other in ipairs(buckets[key]) do
table.insert(collisions, {other, t})
collided[other.id] = true
end
table.insert(buckets[key], t)
end
end
end
return collisions
end

function ball_at(pos)
for j, b in ipairs(balls) do