spade-0.2.0.0: samples/gravity.spd
graphics(true)
let ws = getwindowsize()
let sunx = (ws.width / 2 + 0)
let zoom = 1
let suny = (ws.height / 2)
let sun_radius = 50
let sun_velocity = [0, 0]
let planet_locations = [[100, 400, 0, 0], [130, 400, 0, 0], [150, 400, 0, 0]]
let planet_velocities = [[3.5, -2.9], [3.8, -2.9], [3.9, -2.9]]
-- let planet_velocities = [[0,0 ], [0, 0], [0, 0]]
let forces_on_sun = [[0, 0], [0, 0], [0, 0]]
let net_force_on_sun = [0.0, 0.0]
let paused = false
let lastpause = 0
let planet_mass = 6000
let sun_mass = 50689500
let vec_magnification = 0.1
let gs = getkeystate()
let time_inc = 0.01
loop
clearscreen()
draw_sun_at(sunx, suny)
draw_planets(planet_locations)
if not(paused) then
let net_force_on_sun = [0.0, 0.0]
for i = 1 to size(planet_locations)
let planet_locations[i][1] = (planet_locations[i][1] + planet_velocities[i][1]*time_inc)
let planet_locations[i][2] = (planet_locations[i][2] + planet_velocities[i][2]*time_inc)
let sunx = (sunx + sun_velocity[1]*time_inc)
let suny = (suny + sun_velocity[2]*time_inc)
let accelerating_force_vector = compute_gravity_vector([sunx, suny], planet_locations[i])
let forces_on_sun[i] = [-accelerating_force_vector[1], -accelerating_force_vector[2]]
let net_force_on_sun = [(net_force_on_sun[1] + forces_on_sun[i][1]), (net_force_on_sun[2] + forces_on_sun[i][2])]
let acceleration_x = (accelerating_force_vector[1] / planet_mass)
let acceleration_y = (accelerating_force_vector[2] / planet_mass)
let planet_locations[i][3] = accelerating_force_vector[1]
let planet_locations[i][4] = accelerating_force_vector[2]
let planet_velocities[i][1] = (planet_velocities[i][1] + acceleration_x*time_inc)
let planet_velocities[i][2] = (planet_velocities[i][2] + acceleration_y*time_inc)
endfor
let sun_velocity = [(sun_velocity[1] + (net_force_on_sun[1] / sun_mass)), (sun_velocity[2] + (net_force_on_sun[2] / sun_mass))]
endif
-- handle keyboard input
if inkeystate(gs, scancodes.q) then
break
elseif inkeystate(gs, scancodes.left) then
let sun_velocity[1] = (sun_velocity[1] - 0.0001)
elseif inkeystate(gs, scancodes.right) then
let sun_velocity[1] = (sun_velocity[1] + 0.0001)
elseif inkeystate(gs, scancodes.up) then
let sun_velocity[2] = (sun_velocity[2] - 0.0001)
elseif inkeystate(gs, scancodes.down) then
let sun_velocity[2] = (sun_velocity[2] + 0.0001)
elseif inkeystate(gs, scancodes.z) then
let zoom = zoom + 0.001
println(zoom)
setlogicalsize((ws.width * zoom), (ws.height * zoom))
elseif inkeystate(gs, scancodes.o) then
setlogicalsize(ws.width, ws.height)
elseif inkeystate(gs, scancodes.p) then
let paused = not(paused)
let lastpause = timestamp()
endif
let gs = getkeystate()
render()
endloop
waitforkey()
proc compute_gravity_vector(sun_loc, planet_loc)
let x_delta = (sun_loc[1] - planet_loc[1])
let y_delta = (sun_loc[2] - planet_loc[2])
let distance_sqr = (pow(x_delta, 2) + pow(y_delta, 2))
if (distance_sqr < 300) then
return [0, 0]
endif
let force = ((0.001 * (sun_mass * planet_mass)) / distance_sqr)
let distance = pow(distance_sqr, 0.5)
return [(force * (x_delta / distance)), (force * (y_delta / distance))]
endproc
proc draw_sun_at(x, y)
circle(x, y, sun_radius)
setcolor(50, 250, 250)
foreach forces_on_sun as planet_force
arrow(x, y, (x + (vec_magnification * planet_force[1])), (y + (vec_magnification * planet_force[2])), 5, 5)
endforeach
setcolor(255, 0, 250)
arrow(x, y, (x + (vec_magnification * net_force_on_sun[1])), (y + (vec_magnification * net_force_on_sun[2])), 5, 5)
endproc
proc draw_planets(planets)
setcolor(255, 255, 255)
foreach planets as p
circle(p[1], p[2], 10)
setcolor(255, 0, 0)
arrow(p[1], p[2], (p[1] + (vec_magnification * p[3])), (p[2] + (vec_magnification * p[4])), 5, 5)
setcolor(0, 250, 0)
arrow(p[1], p[2], (p[1] + (vec_magnification * p[3])), p[2], 5, 5)
arrow(p[1], p[2], p[1], (p[2] + (vec_magnification * p[4])), 5, 5)
setcolor(255, 255, 255)
endforeach
endproc