This commit is contained in:
Paul Liverman III 2019-03-07 13:10:47 -08:00
commit 7aa1e676de
3 changed files with 218 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.lua

96
src/main.moon Normal file
View File

@ -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"

121
src/old.moon Normal file
View File

@ -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!