time controls and merging

This commit is contained in:
UndeadMaelys 2022-06-05 19:22:37 +02:00
parent 11ae0f2c66
commit 6affe9d425
2 changed files with 258 additions and 114 deletions

View File

@ -1,26 +1,29 @@
BodyList = {}
Body = class(nil,{type=0})
function newBody(pos,vel,mass,color)
local o = {}
-- coordinates
o.x = pos[1] or 0
o.y = pos[2] or 0
o.z = pos[3] or 0
-- velocities
o.vx = vel[1] or 0
o.vy = vel[2] or 0
o.vz = vel[3] or 0
-- accceleration
o.ax = 0
o.ay = 0
o.az = 0
-- mass
o.mass = mass
-- color
o.color = color
o.max_distance = 0
function newBody(data)
local o = {}
-- coordinates
o.x = data.pos[1] or 0
o.y = data.pos[2] or 0
o.z = data.pos[3] or 0
-- velocities
o.vx = data.vel[1] or 0
o.vy = data.vel[2] or 0
o.vz = data.vel[3] or 0
-- accceleration
o.ax = 0
o.ay = 0
o.az = 0
-- mass
o.mass = data.mass or 1
-- size
o.size = data.size or VIEW.planet_size*math.sqrt(data.mass)
-- color
o.color = data.color or {1,1,1}
o.max_distance = 0
-- origin
o.origin = data.origin or nil
table.insert(BodyList,o)
end

329
main.lua
View File

@ -1,98 +1,223 @@
function love.load()
--options
love.graphics.setColor(1,1,1)
love.graphics.setDefaultFilter("nearest") -- good pixel
SCREEN_WIDTH = love.graphics.getWidth()
SCREEN_HEIGHT = love.graphics.getHeight()
-- simulation variables
CONST_G = 39.5
CONST_S = 0.15
T = 0
DT = 1/120
TIME_SPEED = 0.25
VIEW = {}
VIEW.x = 0
VIEW.y = 0
VIEW.prints = {}
VIEW.orbit_prints = {}
require "class"
SCREEN_WIDTH = love.graphics.getWidth()
SCREEN_HEIGHT = love.graphics.getHeight()
require "class"
require "body"
-- simulation variables
CONST_G = 39.5
CONST_S = 0.15
-- time
T = 0
DT = 1/60
TIME_SPEED = 0.25
CURR_TS = 0
-- view
VIEW = {}
VIEW.x = 0
VIEW.y = 0
VIEW.size = 104
VIEW.planet_size = 40
VIEW.prints = {}
VIEW.print_time = 1/4
VIEW.orbit_prints = {}
VIEW.orbit_print_time = 1500
VIEW.fixated = true
newBody(
{0, 0, 0},
{0, 0, 0},
40000,
{1,0,0}
{
pos = {0, 0, 0},
vel = {-0, 0, 0},
mass = 40000,
color = {1,0,0}
}
)
newBody(
{10000, 0, 0},
{0, 100000, 0},
200,
{0,1,0}
{
pos = {10000, 0, 0},
vel = {0, 100000, 0},
mass = 200,
color = {0,1,0}
}
)
newBody(
{20000, 0, 0},
{0, 100000, 0},
400,
{0,0,1}
{
pos = {20000, 0, 0},
vel = {0, 100000, 0},
mass = 400,
color = {0,0,1}
}
)
newBody(
{0, 20000, 0},
{-200000, 0, 0},
300,
{0,1,1}
{
pos = {0, 20000, 0},
vel = {-200000, 0, 0},
mass = 3000,
color = {0,1,1}
}
)
newBody(
{
pos = {0, -20000, 0},
vel = {200000, 0, 0},
mass = 3000,
color = {0,1,1}
}
)
end
function love.keypressed(key)
if key == "space" then
if CURR_TS == 0 then
CURR_TS = TIME_SPEED
else
CURR_TS = 0
end
end
if key == "up" or key == "right" then
CURR_TS = CURR_TS + 0.1
end
if key == "down" or key == "left" then
CURR_TS = CURR_TS - 0.1
end
CURR_TS = math.max(0, CURR_TS)
if key == "z" then
VIEW.fixated = not VIEW.fixated
end
end
function love.update(dt)
T = math.floor((T + DT * TIME_SPEED)*1000)/1000
UpdateBodiesAcceleration()
UpdateBodiesVelocity(DT * TIME_SPEED)
UpdateBodiesPosition(DT * TIME_SPEED)
T = math.floor((T + DT * CURR_TS)*1000)/1000
-- merge planets that collision
for i=1, #BodyList do
for j=i+1, #BodyList do
if BodyList[i] and BodyList[j] then
local body = BodyList[i]
local other_body = BodyList[j]
local size = body.size/VIEW.size
local other_size = VIEW.planet_size*math.sqrt(other_body.mass)
if math.sqrt(
(other_body.x - body.x) * (other_body.x - body.x) +
(other_body.y - body.y) * (other_body.y - body.y) +
(other_body.z - body.z) * (other_body.z - body.z)
) < (size + other_size) * 2
then
print("matching ".. i .. " and " .. j)
print("original "..i.." pos {"..body.x..", "..body.y..", "..body.z.."}")
print("original "..i.." vel {"..body.vx..", "..body.vy..", "..body.vz.."}")
print("original "..j.." pos {"..other_body.x..", "..other_body.y..", "..other_body.z.."}")
print("original "..j.." vel {"..other_body.vx..", "..other_body.vy..", "..other_body.vz.."}")
local new_x = (body.x + other_body.x) / 2
local new_y = (body.y + other_body.y) / 2
local new_z = (body.z + other_body.z) / 2
print("new pos {"..new_x..", "..new_y..", "..new_z.."}")
local new_vx = (body.vx + other_body.vx) / 2
local new_vy = (body.vy + other_body.vy) / 2
local new_vz = (body.vz + other_body.vz) / 2
print("new vel {"..new_vx..", "..new_vy..", "..new_vz.."}")
local new_mass = body.mass + other_body.mass
print("new mass "..new_mass)
local new_color_r = (body.color[1]+other_body.color[1])/2
local new_color_g = (body.color[2]+other_body.color[2])/2
local new_color_b = (body.color[3]+other_body.color[3])/2
print("new color {"..new_color_r..", "..new_color_g..", "..new_color_b.."}")
newBody(
{
pos = {new_x, new_y, new_z},
vel = {new_vx, new_vy, new_vz},
mass = new_mass,
color = {new_color_r,new_color_g,new_color_b}
}
)
BodyList[i] = nil
BodyList[j] = nil
end
end
end
end
UpdateBodiesAcceleration()
UpdateBodiesVelocity(DT * CURR_TS)
UpdateBodiesPosition(DT * CURR_TS)
-- get previous view offset
local pvx = VIEW.x
local pvy = VIEW.y
-- center camera on bigger one
local vm = 0
for n, body in pairs(BodyList) do
if body.mass > vm then
vm = body.mass
VIEW.x = -body.x
VIEW.y = -body.y
end
end
-- adjust sizes to slowest mass
local vm = 0
for n, body in pairs(BodyList) do
if body.max_distance >= vm then
vm = body.max_distance
VIEW.size = math.sqrt(body.max_distance)
end
end
if VIEW.size == 0 and #BodyList > 0 then
VIEW.fixated = false
VIEW.size = math.sqrt(BodyList[1].mass)
end
-- adjust orbit trails to the reference object
if VIEW.fixated then
for n, print in pairs(VIEW.orbit_prints) do
print.pos.x = print.pos.x - VIEW.x + pvx
print.pos.y = print.pos.y - VIEW.y + pvy
end
end
-- clean list of bodies
local bl = {}
for _, body in pairs(BodyList) do
if body then
table.insert(bl, body)
end
end
BodyList = bl
end
function love.draw()
-- center camera on bigger one
local vm = 0
for n, body in pairs(BodyList) do
if body.mass > vm then
vm = body.mass
VIEW.x = -body.x
VIEW.y = -body.y
end
end
local vm = 0
for n, body in pairs(BodyList) do
if body.max_distance > vm then
vm = body.max_distance
VIEW.size = math.sqrt(body.max_distance)
end
end
love.graphics.setColor(1,1,1)
-- draw bodies
for n, body in pairs(BodyList) do
addPrint(body)
end
drawObitPrints()
drawPrints()
-- draw info
love.graphics.setColor(1,1,1)
love.graphics.print("x,y: " .. VIEW.x .. VIEW.y .. " size: " .. VIEW.size .. " T: ".. T)
for n, body in pairs(BodyList) do
love.graphics.setColor(body.color[1],body.color[2],body.color[3])
love.graphics.print("mass: "..body.mass..", x,y: "..body.x..", "..body.y..", vx, vy:"..body.vx..", "..body.vy,0,15*n)
end
love.graphics.setColor(1,1,1)
-- draw bodies
for n, body in pairs(BodyList) do
addPrint(body)
end
drawObitPrints()
drawPrints()
-- draw info
love.graphics.setColor(1,1,1)
love.graphics.print("x,y: " .. VIEW.x .. VIEW.y .. " size: " .. VIEW.size .. " T: ".. T)
for n, body in pairs(BodyList) do
love.graphics.setColor(body.color[1],body.color[2],body.color[3])
local TT = ""
if body.origin then
TT = "T: " .. body.origin.T
end
love.graphics.print("mass: "..body.mass..TT..", x,y: "..body.x..", "..body.y..", vx, vy:"..body.vx..", "..body.vy,0,15*n)
end
end
function addPrint(body)
VIEW.print_time = 10
table.insert(VIEW.prints,{
pos = {
x = body.x,
@ -102,39 +227,55 @@ function addPrint(body)
color = body.color,
time = VIEW.print_time
})
VIEW.orbit_print_time = 1200
local trail_color = {
(1 + body.color[1])/2,
(1 + body.color[2])/2,
(1 + body.color[3])/2
}
table.insert(VIEW.orbit_prints,{
pos = {
x = body.x,
y = body.y
},
mass = 1,
color = trail_color,
time = VIEW.orbit_print_time
})
local trail_color = {
(1 + body.color[1])/2,
(1 + body.color[2])/2,
(1 + body.color[3])/2
}
if CURRENT_TS ~= 0 then
table.insert(VIEW.orbit_prints,{
pos = {
x = body.x,
y = body.y
},
mass = 1,
color = trail_color,
time = VIEW.orbit_print_time
})
end
end
function drawPrints()
for n, print in pairs(VIEW.prints) do
love.graphics.setColor(print.color[1],print.color[2],print.color[3],print.time/VIEW.print_time)
love.graphics.circle("line",(VIEW.x+print.pos.x)/VIEW.size+SCREEN_WIDTH/2,(VIEW.y+print.pos.y)/VIEW.size+SCREEN_HEIGHT/2,(print.time/VIEW.print_time)*math.sqrt(print.mass)*5/VIEW.size)
print.time = print.time - 1
if print.time < 1 then VIEW.prints[n] = nil end
love.graphics.circle(
"line",
(VIEW.x+print.pos.x)/VIEW.size+SCREEN_WIDTH/2,
(VIEW.y+print.pos.y)/VIEW.size+SCREEN_HEIGHT/2,
VIEW.planet_size * math.sqrt(print.mass)/VIEW.size * (print.time/VIEW.print_time)
)
print.time = print.time - CURR_TS
if print.time < 1
or print.time > VIEW.print_time then
VIEW.prints[n] = nil
end
end
end
function drawObitPrints()
for n, print in pairs(VIEW.orbit_prints) do
love.graphics.setColor(print.color[1],print.color[2],print.color[3],print.time/VIEW.orbit_print_time)
love.graphics.circle("line",(VIEW.x+print.pos.x)/VIEW.size+SCREEN_WIDTH/2,(VIEW.y+print.pos.y)/VIEW.size+SCREEN_HEIGHT/2,(print.time/VIEW.orbit_print_time)*print.mass/VIEW.size)
print.time = print.time - 1
if print.time < 1 then VIEW.orbit_prints[n] = nil end
love.graphics.circle(
"line",
(VIEW.x+print.pos.x)/VIEW.size+SCREEN_WIDTH/2,
(VIEW.y+print.pos.y)/VIEW.size+SCREEN_HEIGHT/2,
print.mass/VIEW.size * (print.time/VIEW.orbit_print_time)
)
print.time = print.time - CURR_TS
if print.time < 1
or print.time > VIEW.orbit_print_time then
VIEW.orbit_prints[n] = nil
end
end
end