init
This commit is contained in:
commit
9554dcba22
123
src/main.moon
Normal file
123
src/main.moon
Normal file
@ -0,0 +1,123 @@
|
||||
math.randomseed os.time!
|
||||
w, h = love.graphics.getDimensions!
|
||||
body_count = 1000
|
||||
starting_area = 1000^2
|
||||
percent_scale = 100 / body_count
|
||||
radius_scale = 1/4
|
||||
G = 100 -- 6.67408e-11
|
||||
-- snapshot doubling ??
|
||||
time, frame_time, sim_rate = 0, 1/60, 1/60
|
||||
|
||||
distance = (A, B) ->
|
||||
local dx, dy
|
||||
dx = A.x - B.x
|
||||
dy = A.y - B.y
|
||||
return math.sqrt dx * dx + dy * dy
|
||||
|
||||
gravity = (A, B) ->
|
||||
local dx, dy, d2, F, theta, cos, sin
|
||||
dx = A.x - B.x
|
||||
dy = A.y - B.y
|
||||
d2 = dx * dx + dy * dy
|
||||
-- return if d2 == 0
|
||||
if d2 <= (A.radius + B.radius)^2
|
||||
return
|
||||
F = G * A.mass * B.mass / d2
|
||||
theta = math.atan2 dy, dx
|
||||
cos = math.cos theta
|
||||
sin = math.sin theta
|
||||
A.vx -= (F / A.mass) * cos * sim_rate
|
||||
A.vy -= (F / A.mass) * sin * sim_rate
|
||||
B.vx += (F / B.mass) * cos * sim_rate
|
||||
B.vy += (F / B.mass) * sin * sim_rate
|
||||
|
||||
class Body
|
||||
new: =>
|
||||
local d, theta
|
||||
d = math.sqrt(starting_area) / 2
|
||||
theta = math.random! * math.pi * 2
|
||||
@x = math.random! * d * math.cos theta
|
||||
@y = math.random! * d * math.sin theta
|
||||
@vx = math.random! / d
|
||||
@vy = math.random! / d
|
||||
@mass = 1
|
||||
@radius = @mass ^ radius_scale
|
||||
|
||||
bodies = {}
|
||||
for i = 1, body_count
|
||||
table.insert bodies, Body!
|
||||
|
||||
simulate = (bodies) ->
|
||||
for i = 1, #bodies - 1, 2
|
||||
for j = i + 1, #bodies
|
||||
gravity(bodies[i], bodies[j])
|
||||
|
||||
for body in *bodies
|
||||
body.x += body.vx * sim_rate
|
||||
body.y += body.vy * sim_rate
|
||||
|
||||
invalid_bodies = {}
|
||||
for i = #bodies, 2, -2
|
||||
for j = i - 1, 1, -1
|
||||
valid = true
|
||||
for id in *invalid_bodies
|
||||
if i == id or j == id
|
||||
valid = false
|
||||
if not valid
|
||||
continue
|
||||
A = bodies[i]
|
||||
B = bodies[j]
|
||||
-- print i, j
|
||||
-- if not A
|
||||
-- print i, j, #bodies
|
||||
if distance(A, B) <= A.radius + B.radius
|
||||
-- print "#{i} and #{j} collided!", distance(A, B), A.radius + B.radius
|
||||
mass = A.mass + B.mass
|
||||
radius = mass ^ radius_scale
|
||||
-- print mass, radius
|
||||
mx = (A.x * A.mass + B.x * B.mass) / mass
|
||||
my = (A.y * A.mass + B.y * B.mass) / mass
|
||||
vx = (A.vx * A.mass + B.vx * B.mass) / mass
|
||||
vy = (A.vy * A.mass + B.vy * B.mass) / mass
|
||||
A.mass = mass
|
||||
A.radius = radius
|
||||
A.x = mx
|
||||
A.y = my
|
||||
A.vx = vx
|
||||
A.vy = vy
|
||||
table.insert(invalid_bodies, j)
|
||||
-- table.remove(bodies, j)
|
||||
-- j += 1
|
||||
|
||||
table.sort invalid_bodies, (a, b) -> a > b
|
||||
for id in *invalid_bodies
|
||||
-- print id
|
||||
table.remove bodies, id
|
||||
-- print "end"
|
||||
|
||||
love.update = (dt) ->
|
||||
simulate bodies
|
||||
|
||||
love.draw = ->
|
||||
if #bodies > 1000
|
||||
return
|
||||
love.graphics.setColor 1, 1, 1, 0.25
|
||||
love.graphics.line 0, h / 2, w, h / 2
|
||||
love.graphics.line w / 2, 0, w / 2, h
|
||||
love.graphics.setColor 1, 1, 1, 1
|
||||
|
||||
love.graphics.translate w / 2, h / 2
|
||||
m, x, y = 0, 0, 0
|
||||
for body in *bodies
|
||||
if body.mass > m
|
||||
m = body.mass
|
||||
x = body.x
|
||||
y = body.y
|
||||
love.graphics.translate -x, -y
|
||||
for body in *bodies
|
||||
-- love.graphics.points body.x, body.y
|
||||
love.graphics.circle "fill", body.x, body.y, body.radius
|
||||
|
||||
love.keypressed = (key) ->
|
||||
if key == "escape"
|
||||
love.event.quit!
|
Loading…
Reference in New Issue
Block a user