using Javis # Planetary data from: https://nssdc.gsfc.nasa.gov/planetary/factsheet/ diameters = Dict( "Mercury" => 4879, "Venus" => 12104, "Earth" => 12756, "Moon" => 3475, "Mars" => 6792, "Jupiter" => 142984, "Saturn" => 120536, "Uranus" => 51118, "Neptune" => 49528, "Pluto" => 2370, ) struct Planet position::Int # Position from the sun name::String gravity::Real # m/s color::String # total guesstimate radius::Real # whatever fake units make the viz pretty end # Automatically calculate radius for us. Calculation is totally arbritrary Planet(pos, name, grav, color) = Planet(pos, name, grav, color, log(diameters[name]) * 2) planets = [ Planet(1, "Mercury", 3.7, "snow4") Planet(2, "Venus", 8.9, "navajowhite") Planet(3, "Earth", 9.8, "lightskyblue") Planet(4, "Moon", 1.6, "gainsboro") Planet(5, "Mars", 3.7, "orangered") Planet(6, "Jupiter", 23.1, "olive") Planet(7, "Saturn", 9, "burlywood") Planet(8, "Uranus", 8.7, "cyan3") Planet(9, "Neptune", 11, "dodgerblue") Planet(10, "Pluto", 0.7, "rosybrown4") ] framerate = 30 height = 1000 # meters | also the video height frames = let # Get planet with slowest acceleration slowest = [p.gravity for p in planets] |> minimum # Kinematic equation to determine seconds to fall from height time = 2 * height / slowest |> sqrt # Calculate total frames and add a few seconds at the end to display final result ceil(Int, time * framerate) + framerate * 10 end function ground(args...) background("black") sethue("white") end font_height = 25 width = 1500 # Give room for header and footer top_padding = font_height * 3 bottom_padding = font_height * 5 + 50 total_height = height + top_padding + bottom_padding myvideo = Video(width, total_height) Background(1:frames, ground) # Determine spacing and make some functions to help space the planets and text spacing = width / (length(planets) + 1) x_calc(planet::Planet) = (planet.position) * spacing - width / 2 + spacing / 2 y_calc(planet::Planet) = -height / 2 + planet.radius y_height(row) = total_height / 2 - font_height / 2 - font_height * row for planet in planets # Kinematic equations to calculate how many frames each planet will be active t_final = 2 * (height - planet.radius * 2) / planet.gravity |> sqrt v_final = planet.gravity * t_final frame_final = ceil(Int, t_final * framerate) for f = 1:frame_final # Calculate time of current frame for kinematic math time = f / framerate # Calculate planets current position planet_y = 0.5 * planet.gravity * time^2 - height / 2 # Set the planets position Object( f:f, JCircle(O, planet.radius, color = planet.color, action = :fill), Point(x_calc(planet), planet_y + planet.radius), ) # Update text for planets current state Object( f:f, @JShape begin fontsize(font_height) text( string(round((f - 1) / frames * framerate, digits = 1), "s"), Point(x_calc(planet), y_height(1)), halign = :center, ) text( string(round(planet.gravity * time, digits = 2), "m/s"), Point(x_calc(planet), y_height(0)), halign = :center, ) end ) # Leave a trail every few seconds to give an idea of the acceleration happening if f % framerate * 4 == 0 Object( f:frames, JCircle(O, planet.radius / 5, color = planet.color, action = :fill), Point(x_calc(planet), planet_y), ) end end # Make the planet sit at the bottom of the video for the rest of the frames Object( frame_final:frames, JCircle(O, planet.radius, color = planet.color, action = :fill), Point(x_calc(planet), height / 2 - planet.radius), ) # Set all the text for after the planet is done moving Object( frame_final:frames, @JShape begin fontsize(font_height) sethue("green") text(planet.name, Point(x_calc(planet), y_height(3)), halign = :center) text( string(planet.gravity, "m/s^2"), Point(x_calc(planet), y_height(2)), halign = :center, ) text( string(round(t_final, digits = 1), "s"), Point(x_calc(planet), y_height(1)), halign = :center, ) text( string(round(v_final, digits = 2), "m/s"), Point(x_calc(planet), y_height(0)), halign = :center, ) end ) # Set text that is static during entire planet translation Object( 1:frame_final, @JShape begin fontsize(font_height) text(planet.name, Point(x_calc(planet), y_height(3)), halign = :center) text( string(planet.gravity, "m/s^2"), Point(x_calc(planet), y_height(2)), halign = :center, ) end ) end # Set the legend text Object( 1:frames, @JShape begin fontsize(font_height) x_pt = -width / 2 + 10 text("1km", Point(x_pt, -height / 2 + font_height), halign = :left) text("0km", Point(x_pt, height / 2), halign = :left) fontsize(font_height * 0.75) text("Planet:", Point(x_pt, y_height(3)), halign = :left) text("Acceleration:", Point(x_pt, y_height(2)), halign = :left) text("Time:", Point(x_pt, y_height(1)), halign = :left) text("Velocity:", Point(x_pt, y_height(0)), halign = :left) fontsize(font_height * 2) sethue("royalblue") text( "Ball Falling 1km on Bodies in the Solar System", Point(0, -height / 2 - font_height * 2), halign = :center, ) end ) render(myvideo; liveview = true) # render(myvideo; pathname = "hacktober.gif")