commit 7aa1e676de08d27fdbda8c3b3d9f44071f2132db Author: Paul Liverman III Date: Thu Mar 7 13:10:47 2019 -0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d907c43 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.lua diff --git a/src/main.moon b/src/main.moon new file mode 100644 index 0000000..302bbe5 --- /dev/null +++ b/src/main.moon @@ -0,0 +1,96 @@ +width, height = love.graphics.getDimensions! +radius = (width + height) / 4 + +class Particle + new: (n=1, x, y, r=radius) => + rng = love.math.newRandomGenerator n + @color = { rng\random!, rng\random!, rng\random!, 1 } + @mass = n + @charge = n % math.log(n) + @radius = math.log(n + 8) + if x and y + @x = x + @y = y + else + d = love.math.random! * r + r = love.math.random! * math.pi * 2 + @x = d * math.sin r + @y = d * math.cos r + @vx = 0 + @vy = 0 + +universe = {} +new = {} +for i=1,800 + table.insert universe, Particle nil, nil, nil, 200 + +physics = (a, b) -> + dx = a.x - b.x + dy = a.y - b.y + d2 = dx * dx + dy * dy + theta = math.atan2 dy, dx + x = math.cos theta + y = math.sin theta + r2 = (a.radius + b.radius)^2 + m = a.mass + b.mass + if d2 > r2 + g = 1 / d2 + a.vx -= b.mass * g * x + a.vy -= b.mass * g * y + b.vx += a.mass * g * x + b.vy += a.mass * g * y + -- elseif d2 < math.log(r2) / m^2 + -- p = Particle m + -- p.vx = a.vx / a.mass + b.vx / b.mass + -- p.vy = a.vy / a.mass + b.vy / b.mass + -- p.x = (a.x * a.mass + b.x * b.mass) / m + -- p.y = (a.y * a.mass + b.y * b.mass) / m + -- a.dirty = true + -- b.dirty = true + -- table.insert new, p + else + f = math.min 1, 100 / math.max d2, 0.01 + a.vx += f * x + a.vy += f * y + b.vx -= f * x + b.vy -= f * y + a.vx *= 0.99 + a.vy *= 0.99 + b.vx *= 0.99 + b.vy *= 0.99 + -- a.x += x + -- a.y += y + -- b.x -= x + -- b.y -= y + +love.update = (dt) -> + for a = 1, #universe - 1 + for b = a + 1, #universe + physics(universe[a], universe[b]) + + for i = #universe, 1, -1 + if universe[i].dirty + table.remove universe, i + i += 1 + + while next new + table.insert universe, table.remove new, 1 + + for particle in *universe + particle.x += particle.vx * dt + particle.y += particle.vy * dt + +love.mousepressed = (x, y) -> + for i = 1, 25 + X = x - width / 2 + love.math.random -25, 25 + Y = y - height / 2 + love.math.random -25, 25 + table.insert universe, Particle 1, X, Y + +love.draw = -> + love.graphics.translate width / 2, height / 2 + for particle in *universe + love.graphics.setColor particle.color + love.graphics.circle "fill", particle.x, particle.y, particle.radius + +love.keypressed = (key) -> + love.event.quit! if key == "escape" diff --git a/src/old.moon b/src/old.moon new file mode 100644 index 0000000..f2eedd1 --- /dev/null +++ b/src/old.moon @@ -0,0 +1,121 @@ +-- particle type influences attractive/repulsive forces +-- heat +width, height = love.graphics.getDimensions! +clamp = (n, x, y) -> math.max x, math.min y, n +sign = (n) -> math.abs(n) == n and 1 or -1 + +class Particle + new: (n=1, x, y) => + rng = love.math.newRandomGenerator n + @color = { rng\random!, rng\random!, rng\random!, 1 } + @mass = n + @charge = n % 5 - 2 + @radius = math.log(n + 10) + @x = x or love.math.random 0, width + @y = y or love.math.random 0, height + @vx = 0 + @vy = 0 + +universe = {} +new = {} +for i=1,500 + table.insert universe, Particle love.math.random 1, 5 +-- table.insert universe, Particle 1, width / 2 - 4, height / 2 - 200 +-- table.insert universe, Particle 5, width / 2 + 4, height / 2 - 200 +-- table.insert universe, Particle 1, width / 2 - 4, height / 2 + 200 +-- table.insert universe, Particle 1, width / 2 + 4, height / 2 + 200 + +physics = (a, b) -> + -- distance, direction, collision checks + dx = a.x - b.x + dy = a.y - b.y + d2 = dx * dx + dy * dy + theta = math.atan2 dy, dx + x = math.cos theta + y = math.sin theta + r2 = (a.radius + b.radius)^2 + m = a.mass + b.mass + if d2 > r2 + -- gravitational force + g = 1 / d2 + a.vx -= b.mass * g * x + a.vy -= b.mass * g * y + b.vx += a.mass * g * x + b.vy += a.mass * g * y + -- electromotive force + unless a.charge == 0 or b.charge == 0 + e = (math.abs(a.charge) + math.abs(b.charge))^3 / d2^2 + -- print a.charge, b.charge, e + if sign(a.charge) == sign(b.charge) + a.vx -= b.charge * e * x + a.vy -= b.charge * e * y + b.vx += a.charge * e * x + b.vy += a.charge * e * y + else + a.vx -= b.charge * e * x + a.vy -= b.charge * e * y + b.vx -= a.charge * e * x + b.vy -= a.charge * e * y + elseif d2 < math.log(r2) / m^3 / 10 + -- making new elements + p = Particle m + p.vx = a.vx / a.mass + b.vx / b.mass + p.vy = a.vy / a.mass + b.vy / b.mass + p.x = (a.x * a.mass + b.x * b.mass) / m + p.y = (a.y * a.mass + b.y * b.mass) / m + a.dirty = true + b.dirty = true + table.insert new, p + else + -- anti-collision force + f = math.min 0.4, 100 / math.max d2, 0.01 + a.vx += b.mass * f * x + a.vy += b.mass * f * y + b.vx -= a.mass * f * x + b.vy -= a.mass * f * y + +love.update = (dt) -> + for a = 1, #universe - 1 + for b = a + 1, #universe + physics(universe[a], universe[b]) + + for i=#universe, 1, -1 + if universe[i].dirty + table.remove universe, i + i += 1 + + while next new + table.insert universe, table.remove new, 1 + + for particle in *universe + -- particle.vx *= 0.9 + -- particle.vy *= 0.9 + particle.x += particle.vx * dt + particle.y += particle.vy * dt + +love.draw = -> + types = {} + for particle in *universe + if types[particle.mass] + types[particle.mass] += 1 + else + types[particle.mass] = 1 + love.graphics.setColor particle.color + love.graphics.circle "fill", particle.x, particle.y, particle.radius + + -- love.graphics.setColor 1, 1, 1, 0.5 + -- love.graphics.line width / 2, 0, width / 2, height + love.graphics.setColor 1, 1, 1, 1 + love.graphics.print #universe + for i,v in ipairs types + love.graphics.print "#{i}->#{v}", 0, i * 12 + +love.mousepressed = (x, y) -> + for i=1,50 + a = x + love.math.random -25, 25 + b = y + love.math.random -25, 25 + table.insert universe, Particle 1, a, b + +love.keypressed = (key) -> + love.event.quit! if key == "escape" + table.insert universe, Particle!