## Earth & Ships

```
using AbstractPlotting: textslider
using GeometryBasics, FileIO
using LinearAlgebra

using AbstractPlotting

"""
example by @pbouffard from JuliaPlots/Makie.jl#307
https://github.com/pbouffard/miniature-garbanzo/
"""

const rearth_km = 6371.1f0
const mearth_kg = 5.972e24
const rmoon_km = 1738.1f0
const mmoon_kg = 7.34e22
const rship_km = 500f0
const mship_kg = 1000.0
const dbetween_km = 378_000.0f0
const timestep = 1.0f0

mutable struct Ship
mass_kg::Float32
position_m::Vec3f0
velocity_mps::Vec3f0
color::Symbol
mesh::AbstractPlotting.Mesh
end

function moveto!(ship::Ship, (x, y, z))
ship.position_m = Vec3f0(x, y, z)
translate!(ship.mesh, x, y, z)
ship.position_m, ship.velocity_mps
end

function orbit(r; steps=80)
return [Point3f0(r*cos(x), r*sin(x), 0) for x in range(0, stop=2pi, length=steps)]
end

# http://corysimon.github.io/articles/uniformdistn-on-sphere/
function makestars(n)
return map(1:n) do i
v = [0, 0, 0]  # initialize so we go into the while loop
while norm(v) < .0001
v = randn(Point3f0)
end
v = v / norm(v)  # normalize to unit norm
v
end
end

function makecontrols()
orbit_slider, orbit_speed = textslider(0f0:10f0, "Speed", start=1.0)
scale_slider, scale = textslider(1f0:20f0, "Scale", start=10.0)
return orbit_slider, orbit_speed, scale_slider, scale
end

function makeships(scene, N)
return map(1:N) do i
sm = mesh!(scene, Sphere(Point3f0(0), rship_km*radius_mult), color=:green, show_axis=false)[end]
ship = Ship(mship_kg, [0, 0, 0], [0, 0, 0], :green, sm)
moveto!(ship, (100000f0 * randn(Float32), dbetween_km/2 + randn(Float32) * 50000f0, 50000f0*randn(Float32)))
ship.velocity_mps = [40000*randn(Float32), -1000*randn(Float32), 1000*randn(Float32)]
ship
end
end

function makeobjects(scene)
earth = mesh!(scene, Sphere(Point3f0(0), rearth_km*radius_mult), color=earthbitmap)[end]

moon = mesh!(scene, Sphere(Point3f0(0), rmoon_km*radius_mult), color=moonbitmap)[end]
translate!(moon, Vec3f0(0, dbetween_km, 0))
orb = lines!(scene, orbit(dbetween_km), color=:gray)
# stars = scatter!(1000000*makestars(1000), color=:white, markersize=2000)

return earth, moon #, stars#, ships
end

function spin(scene, orbit_speed, scale, moon, earth, ships)
center!(scene) # update far / near automatically.
# could also be done manually:
# cam.near[] = 100
# cam.far[] = 1.5*dbetween_km
update_cam!(scene, Vec3f0(1.3032e5, 7.12119e5, 3.60022e5), Vec3f0(0, 0, 0))
θ = 0.0
# wait untill window is open
while !isopen(scene)
sleep(0.1)
end
while isopen(scene)
scale!(moon, (scale[], scale[], scale[]))
scale!(earth, (scale[], scale[], scale[]))
for ship in ships
scale!(ship.mesh, (scale[], scale[], scale[]))
end
translate!(moon, Vec3f0(-dbetween_km*sin(θ/28), dbetween_km*cos(θ/28), 0))
rotate!(earth, Vec3f0(0, 0, 1), θ)
rotate!(moon, Vec3f0(0, 0, 1), π/2 + θ/28)
sleep(0.01)
θ += 0.05 * orbit_speed[]
timestep = 10 * orbit_speed[]
gravity(timestep, ships, earth, moon)
end
end

function gravity(timestep, ships, earth, moon)
for ship in ships
rship = ship.position_m #translation(ship)[]
rearth = translation(earth)[]
rmoon = translation(moon)[]
rship_earth = (rearth - rship) * 1e3 # convert to m
rship_moon = (rmoon - rship) * 1e3 # convert to m
G = 6.67408e-11 # m^3⋅kg^-2⋅s^-1
nrship_earth = max(0.1, norm(rship_earth))
nrship_moon = max(0.1, norm(rship_moon))
fearth = G * (mship_kg * mearth_kg)/(nrship_earth^2) * rship_earth/nrship_earth
fmoon = G * (mship_kg * mmoon_kg)/(nrship_moon^2) * rship_earth/nrship_earth
ftot = fearth + fmoon
ship.velocity_mps += timestep * ftot
drship = timestep * ship.velocity_mps / 1e3
rship = rship + drship
moveto!(ship, rship)
end
end
universe = Scene(backgroundcolor=:black, show_axis=false, resolution=(2048,1024))
ships = makeships(universe, 600)
earth, moon = makeobjects(universe);
orbit_slider, orbit_speed, scale_slider, scale = makecontrols();
controls = (orbit_slider, scale_slider);
scene = hbox(vbox(controls...), universe)
universe.center = false
task = @async spin(universe, orbit_speed, scale, moon, earth, ships)
scene.center = false

# Do not execute beyond this point!

RecordEvents(scene, "output")

```