Permalink
Cannot retrieve contributors at this time
| -- boids | |
| -- t gill 190925 | |
| -- inspired by http://www.vergenet.net/~conrad/boids/pseudocode.html | |
| -- params | |
| follow = 0.75 -- input=1, free=0 | |
| pull = 0.5 -- to centre | |
| avoid = 0.1 -- V threshold | |
| sync = 1/20 -- dir attraction | |
| limit = 0.05 -- max volts per timestep | |
| timing = 0.02 -- calc speed | |
| boids = {} | |
| count = 4 | |
| -- artificially provide a 'centre-of-mass' | |
| function centring(b,c) | |
| return (c - b.p) * pull | |
| end | |
| function avoidance(bs,b) | |
| v = 0 | |
| for n=1,count do | |
| if bs[n] ~= b then -- ignore self | |
| d = bs[n].p - b.p | |
| if math.abs(d) < avoid then | |
| v = v - d/2 | |
| end | |
| end | |
| end | |
| return v | |
| end | |
| function syncing(bs,b) | |
| v = 0 | |
| for n=1,count do | |
| if bs[n] ~= b then -- ignore self | |
| v = v + bs[n].v | |
| end | |
| end | |
| v = v / (count-1) | |
| return (v - b.v) * sync | |
| end | |
| function findcentre(bs,c) | |
| m = 0 | |
| for n=1,count do | |
| m = m + bs[n].p | |
| end | |
| m = m/count | |
| return m + follow*(c-m) | |
| end | |
| function move( bs, n, c, v ) | |
| mass = findcentre(bs,c) | |
| b = bs[n] | |
| v1 = centring(b,mass) | |
| v2 = avoidance(bs,b) | |
| v3 = syncing(bs,b) | |
| b.v = b.v + v1 + v2 + v3 | |
| if b.v > limit then b.v = limit | |
| elseif b.v < -limit then b.v = -limit end | |
| b.v = b.v * v | |
| b.p = b.p + b.v | |
| return b | |
| end | |
| function draw( b, n, v ) | |
| output[n].slew = v*1.1 | |
| output[n].volts = b.p | |
| end | |
| -- round-robin calculation | |
| function step(c) | |
| c = (c % count)+1 | |
| accel = input[2].volts | |
| draw( boids[c], c, timing ) | |
| boids[c] = move( boids, c, input[1].volts, (accel+5.0)/5.0 ) | |
| end | |
| function init_boids() | |
| local bs = {} | |
| for n=1,count do | |
| bs[n] = { p = math.random()*3.0 - 1.0 | |
| , v = 0 | |
| } | |
| end | |
| return bs | |
| end | |
| function init() | |
| boids = init_boids() | |
| mover = metro.init{ event = step | |
| , time = timing/count | |
| , count = -1 | |
| } | |
| mover:start() | |
| end |