Black Holes, Orbiting Bodies, and Anomalies -- Oh my!

Greetings all -

I'm fairly new to lua scripting, but am excited about the possibilities of doing so for Empty Epsilon. One of the cool things I discovered with EE was the ability to have space bodies in motion - because of course space is a lot more fun when you have things moving around! So I started experimenting with what could be done, and thought maybe others might like to use as well. I will add snippets here as I'm able.

First up, I wanted to try planets orbiting a black hole at different rates, that had moons that also had moons themselves. Here's what I came up with:


function init()

   	-- BLACK HOLE ORBITING SYSTEM TEST
		-- initial alignment of objects is along the X axis (X value is the same; Y changes for distance from center)
		-- the center object
		center_blackhole = BlackHole():setPosition(0, 0)
		-- "on the edge" planet orbiting just outside the event horizon, very fast
		cbh_event_horizon1 = Planet():setPosition(0, -6000):setPlanetRadius(500)
			:setDistanceFromMovementPlane(-2000)
			:setPlanetSurfaceTexture("planets/planet-1.png")
			:setPlanetCloudTexture("planets/clouds-1.png")
			:setPlanetAtmosphereTexture("planets/atmosphere.png")
			:setPlanetAtmosphereColor(0.2,0.2,1.0)
		cbh_event_horizon1:setOrbit(center_blackhole, 5)
		-- "near the edge" planet orbiting near the event horizon, fast
		cbh_event_horizon2 = Planet():setPosition(0, -10000):setPlanetRadius(1000)
			:setDistanceFromMovementPlane(-2000)
			:setPlanetSurfaceTexture("planets/planet-1.png")
			:setPlanetCloudTexture("planets/clouds-1.png")
			:setPlanetAtmosphereTexture("planets/atmosphere.png")
			:setPlanetAtmosphereColor(0.2,0.2,1.0)
		cbh_event_horizon2:setOrbit(center_blackhole, 15)

		-- planetary orbital sub-system 1, to the 'north' of sun1
			cbh_main_planet1 = Planet():setPosition(0, -30000):setPlanetRadius(3000)
				:setDistanceFromMovementPlane(-2000):setAxialRotationTime(30)
				:setPlanetSurfaceTexture("planets/planet-1.png")
				:setPlanetCloudTexture("planets/clouds-1.png")
				:setPlanetAtmosphereTexture("planets/atmosphere.png")
				:setPlanetAtmosphereColor(0.2,0.2,1.0)
			cbh_main_planet1:setOrbit(center_blackhole, 300)
			-- orbiting bodies for cbh_main_planet1, inner to outer
				mp1_satelite1 = Planet():setPosition(0, -24000):setPlanetRadius(500)
					:setDistanceFromMovementPlane(-2000):setAxialRotationTime(30)
					:setPlanetSurfaceTexture("planets/planet-1.png")
					:setPlanetCloudTexture("planets/clouds-1.png")
					:setPlanetAtmosphereTexture("planets/atmosphere.png")
					:setPlanetAtmosphereColor(0.2,0.2,1.0)
				mp1_satelite1:setOrbit(cbh_main_planet1, 10)
				
				mp1_satelite2 = Planet():setPosition(0, -20000):setPlanetRadius(1000)
					:setDistanceFromMovementPlane(-2000):setAxialRotationTime(30)
					:setPlanetSurfaceTexture("planets/planet-1.png")
					:setPlanetCloudTexture("planets/clouds-1.png")
					:setPlanetAtmosphereTexture("planets/atmosphere.png")
					:setPlanetAtmosphereColor(0.2,0.2,1.0)
				mp1_satelite2:setOrbit(cbh_main_planet1, 60)

				mp1s2_satelite1 = Planet():setPosition(0, -18000):setPlanetRadius(200)
					:setDistanceFromMovementPlane(-2000):setAxialRotationTime(10)
					:setPlanetSurfaceTexture("planets/planet-1.png")
					:setPlanetCloudTexture("planets/clouds-1.png")
					:setPlanetAtmosphereTexture("planets/atmosphere.png")
					:setPlanetAtmosphereColor(0.2,0.2,1.0)
				mp1s2_satelite1:setOrbit(mp1_satelite2, 5)

				mp1_satelite3 = Planet():setPosition(0, -16000):setPlanetRadius(500)
					:setDistanceFromMovementPlane(-2000):setAxialRotationTime(30)
					:setPlanetSurfaceTexture("planets/planet-1.png")
					:setPlanetCloudTexture("planets/clouds-1.png")
					:setPlanetAtmosphereTexture("planets/atmosphere.png")
					:setPlanetAtmosphereColor(0.2,0.2,1.0)
				mp1_satelite3:setOrbit(cbh_main_planet1, 60)
end

Because all the code in init() follows the constructs already established in EE, no additional code is needed in the update() function.

Enjoy!

Comments

  • Next, I wanted to create a binary black hole system. EE doesn't provide for BH's orbiting other bodies natively, so I came up with my own. 8-)

    And for good measure, I added a planet orbiting one of the BH's and a huge space station orbiting the other! (Yes, this is how you can have stations orbiting other entities.)

    Please note that I've hard coded the orbital speed to something that's easy to observe for a test. You may want to slow the speed down a bit… otherwise the people inhabiting the space station might be crushed to goo from the G forces… ;]

    Note that you create the bodies in the init() function, then move them in the update(delta) function.

    Also note that you must "require("utils.lua")"
    
    require("utils.lua")
    
    function init()
    	-- BINARY BLACK HOLE AROUND A SINGLE STAR TEST
    		cs_x_coord = 0
    		cs_y_coord = 0
    		obh1_distance = 40000
    		obh2_distance = 40000
    		
    		center_star = Planet():setPosition(cs_x_coord, cs_y_coord)
    			:setPlanetRadius(1000):setDistanceFromMovementPlane(-2000)
    			:setPlanetAtmosphereTexture("planets/star-1.png")
    			:setPlanetAtmosphereColor(1.0,1.0,1.0)
    		orbiting_blackhole_1 = BlackHole():setPosition(cs_x_coord, cs_y_coord + obh1_distance)
    		orbiting_blackhole_2 = BlackHole():setPosition(cs_x_coord, cs_y_coord - obh2_distance)
    		
    		-- for this test, set the orbital speed to 1 orbit/min; because the update function is called 
    		--approximately 60 times a second, that means we'd update the position around the orbit 
    		-- (60 calls/sec * 60 sec = 3600 calls)
    		-- 360 degrees / 3600 calls = 0.1 degree of arc per call (go to the update function for movement calculations)
    		orbiting_blackhole1_angle = 180
    		orbiting_blackhole2_angle = 0
    	
    		-- set up some planets to orbit the orbiting black holes
    		local x, y = orbiting_blackhole_1:getPosition()
    		obh1_orbiting_planet1 = Planet():setPosition(x, y-10000):setPlanetRadius(1000)
    			:setDistanceFromMovementPlane(0):setAxialRotationTime(20)
    			:setPlanetSurfaceTexture("planets/planet-1.png")
    			:setPlanetCloudTexture("planets/clouds-1.png")
    			:setPlanetAtmosphereTexture("planets/atmosphere.png")
    			:setPlanetAtmosphereColor(0.2,0.2,1.0)
    		obh1_orbiting_planet1:setOrbit(orbiting_blackhole_1, 8)
    		
    		-- test to have a station orbit the orbiting black holes
    		local x, y = orbiting_blackhole_2:getPosition()
    		obh2_orbiting_station1_orbit_distance = 10000
    		obh2_orbiting_station1 = SpaceStation():setPosition(x, y + obh2_orbiting_station1_orbit_distance)
    			:setTemplate('Huge Station'):setFaction("Human Navy"):setRotation(random(0, 360))
    		obh2_orbiting_station1_angle = 0
       	
    end
    

    Add the following in the update() function.
    
    function update(delta)
    	-- move the binary black holes in orbit around the shared star
    		
    		orbiting_blackhole1_angle = orbiting_blackhole1_angle + 0.1
    		if orbiting_blackhole1_angle > 360 then orbiting_blackhole1_angle = 0.1 end
    		
    		orbiting_blackhole2_angle = orbiting_blackhole2_angle + 0.1
    		if orbiting_blackhole2_angle > 360 then orbiting_blackhole2_angle = 0.1 end
    		
    		obh2_orbiting_station1_angle = obh2_orbiting_station1_angle + 0.5
    		if obh2_orbiting_station1_angle > 360 then obh2_orbiting_station1_angle = 0.5 end
    		
    		setCirclePos(orbiting_blackhole_1, cs_x_coord, cs_y_coord, orbiting_blackhole1_angle, obh1_distance)
    		setCirclePos(orbiting_blackhole_2, cs_x_coord, cs_y_coord, orbiting_blackhole2_angle, obh2_distance)
    		
    		-- note that because station objects don't have a built-in function to have them orbit something else, 
    		-- then we must take care of it ourselves
    		local x, y = orbiting_blackhole_2:getPosition()
    		setCirclePos(obh2_orbiting_station1, x, y, obh2_orbiting_station1_angle, obh2_orbiting_station1_orbit_distance)
    		
    end
    
    
    Enjoy!
  • edited November 2018
    Ok, now let's get a little funky! Let's create a system with an orbiting planet, and the planet has a moon. It just so happens that there's another system with a planet whose orbit passes close to the first one. So close in fact, that the moon of the first planet decides to "hop" over to the second planet. Yea, kinda funky. I wouldn't want to see what would happen to this system in real life, but this is a game so it's kinda fun! ;]

    Note that you create the bodies in the init() function, then move them in the update(delta) function.

    Also note that you must "require("utils.lua")"
    
    require("utils.lua")
    
    function init()
    	-- STEAL AN ORBITING MOON TEST
    		-- the general idea is that there are two large planets orbiting two separate suns; there is one moon orbiting one of the planets; 
    		-- because the orbits of the two planets come close to one another, if the moon of the first planet passes closer to the second 
    		-- planet than the first, the idea is that it should "hop" planets and begin orbiting the second planet
    		-- crazy, yes
    		-- set up all on the same y value, separated along the x axis value
    		
    		-- establish a flag to state which planet the shared_moon is currently orbiting; 
    		-- 1 means planet 1 on the left side; 2 means planet 2 on the right side
    			moon_orbit_owner = 1
    			
    		-- first side (left)
    			star1_x_position = 0                        
    			star1_y_position = 0                         
    			planet1_x_start_position = star1_x_position - 40000
    			planet1_y_start_position = star1_y_position
    			shared_moon_x_start_position = planet1_x_start_position - 10000
    			shared_moon_y_start_position = planet1_y_start_position
    			
    			star1 = Planet():setPosition(star1_x_position, star1_y_position)
    				:setPlanetRadius(5000)
    				:setDistanceFromMovementPlane(-2000)
    				:setPlanetAtmosphereTexture("planets/star-1.png")
    				:setPlanetAtmosphereColor(1.0,1.0,1.0)
    			
    			planet1 = Planet():setPosition(planet1_x_start_position, planet1_y_start_position)
    				:setPlanetRadius(3000)
    				:setDistanceFromMovementPlane(-2000)
    				:setPlanetSurfaceTexture("planets/planet-1.png")
    				:setPlanetCloudTexture("planets/clouds-1.png")
    				:setPlanetAtmosphereTexture("planets/atmosphere.png")
    				:setPlanetAtmosphereColor(0.2,0.2,1.0)
    			
    			planet1:setOrbit(star1, 120)
    			
    			shared_moon = Planet():setPosition(shared_moon_x_start_position, shared_moon_y_start_position)
    				:setPlanetRadius(1000)
    				:setDistanceFromMovementPlane(-2000)
    				:setPlanetSurfaceTexture("planets/planet-1.png")
    				:setPlanetCloudTexture("planets/clouds-1.png")
    				:setPlanetAtmosphereTexture("planets/atmosphere.png")
    				:setPlanetAtmosphereColor(0.2,0.2,1.0)
    			shared_moon:setOrbit(planet1, 15)
    		
    		-- second side (right)
    			star2_x_position = star1_x_position + 95000                
    			star2_y_position = star1_y_position                        
    			planet2_x_start_position = star2_x_position + 40000
    			planet2_y_start_position = star2_y_position
    		
    			star2 = Planet():setPosition(star2_x_position, star2_y_position)
    				:setPlanetRadius(5000)
    				:setDistanceFromMovementPlane(-2000)
    				:setPlanetAtmosphereTexture("planets/star-1.png")
    				:setPlanetAtmosphereColor(1.0,1.0,1.0)
    			
    			planet2 = Planet():setPosition(planet2_x_start_position, planet2_y_start_position)
    				:setPlanetRadius(3000)
    				:setDistanceFromMovementPlane(-2000)
    				:setPlanetSurfaceTexture("planets/planet-1.png")
    				:setPlanetCloudTexture("planets/clouds-1.png")
    				:setPlanetAtmosphereTexture("planets/atmosphere.png")
    				:setPlanetAtmosphereColor(0.2,0.2,1.0)
    			
    			planet2:setOrbit(star2, 120)
    		
    end
    

    Add the following in the update() function.
    
    function update(delta)
    	-- moon hop between planet check
    		
    		-- get distance to planet 1
    		distance_to_planet1 = distance(planet1, shared_moon)
    		-- get distance to planet 2
    		distance_to_planet2 = distance(planet2, shared_moon)
    		
    		if moon_orbit_owner == 1 and distance_to_planet2 < distance_to_planet1 then
    			moon_orbit_owner = 2
    			shared_moon:setOrbit(planet2, 15)
    		elseif moon_orbit_owner == 2 and distance_to_planet1 < distance_to_planet2 then
    			moon_orbit_owner = 1
    			shared_moon:setOrbit(planet1, 15)
    		end
    
    end
    
    

    Give that a try! Enjoy!
  • edited November 2018
    Next, I wanted to experiment with a black hole being able to capture a body a little further away and then draw it into itself like a whirlpool. I intend to expand on this basic idea, but here's at least the first part. And I definitely want the objects to accelerate as they get closer to the black hole; currently they appear as if to slow down. Will hopefully get to that soon.

    Note that you create the bodies in the init() function, then move them in the update(delta) function.

    Also note that you must "require("utils.lua")"
    
    require("utils.lua")
    
    function init()
    	-- WHIRLPOOL OF DEATH TEST
    		-- the basic idea is to create a curving "whirlpool" that captures stuff and spirals them inward towards a black hole 
    		
    		whirlpool_bh_x_position = 0
    		whirlpool_bh_y_position = 0
    		
    		whirlpool_blackhole = BlackHole():setPosition(whirlpool_bh_x_position, whirlpool_bh_y_position)
    		
    		-- the travel time is the number of seconds that a single nebula should take from the start position to get to the black hole
    		travel_time = 30
    		
    		-- tt_iterations is simply the travel time multiplied to account for the number of times that the update function is called per second
    		tt_iterations = travel_time * 60
    		
    		-- the degree of coverage is the heading where the nebula begins the spiral journey; for now, must remain < 360 to keep the math simple
    		degree_of_coverage = 315
    		current_degree_angle = degree_of_coverage
    		
    		-- the radius distance will be calculated from the whirlpool_blackhole position
    		radius_distance_to_start = 80000
    		current_radius_distance = radius_distance_to_start
    		
    		-- the delta_radius_distance is the amount of radius shrinkage that needs to occur for each call of update in order for the nebula to 
    		-- arrive at the blackhole in the travel_time specified
    		delta_radius_distance = radius_distance_to_start / tt_iterations
    		
    		-- delta_degrees is the amount of travel around the spiral that the nebula must travel each call of update in order for the nebula to arrive 
    		-- at the blackhole in the travel_time specified
    		delta_degrees = degree_of_coverage / tt_iterations
    		
    		test_traveling_nebula = Nebula()
    		
    		-- it appears that the 'setCirclePosition' function treats the X axis of the unit circle as the 0-180 axis, with 0 being to the right; not sure why this is
    		-- 0 should be straight up the Y axis (need to consider adding a corrected function to utils.lua)
    		setCirclePos(test_traveling_nebula, whirlpool_bh_x_position, whirlpool_bh_y_position, degree_of_coverage, radius_distance_to_start)
    	
    end
    

    Add the following in the update() function.
    
    function update(delta)
    	-- WHIRLPOOL TRAVELING NEBULA update
    		
                    if test_traveling_nebula:isValid() then
    			-- first decrement both the radius distance and the degree angle
    			current_radius_distance = current_radius_distance - delta_radius_distance
    			current_degree_angle = current_degree_angle - delta_degrees
    			-- setCirclePos(obj, x, y, angle, distance)
    			setCirclePos(test_traveling_nebula, whirlpool_bh_x_position, whirlpool_bh_y_position, current_degree_angle, current_radius_distance)		
    		end
    end
    
    

    Give that a try and watch a nebula spiral into a black hole. Quite satisfying! Enjoy!
  • Awesome, I stealing this to go with my Plasma Storm :)
  • Love to see it when you're finished!
  • edited November 2018
    Question - I'm not sure about the "DistanceFromMovementPlane" attribute, and I'm probably using it wrong in the examples above. Can anyone help me out and give me a clue? I searched this site as well as the wiki and couldn't find anything definitive on it.

    Thanks in advance!
  • That's simply the "z" position. Hench, the distance from the plane where the other objects move.
  • Aha! Yes, now that makes sense. Thanks Daid!
  • Ok, here's another one for you. This one is a blackhole with 2 orbiting bands of nebula and one band of asteroids. The nebula are in clumps that orbit at the same speed within a band, but the asteroids are randomly distributed in their band. Oh, and the asteroid band rotates opposite to the nebula bands. ;]

    The cool thing is much of the setup is handled by variables that gives you easy control on where to put the system, the radius of the bands from the blackhole center, the density of nebula and the degree of spread, as well as the number of asteroids and their velocity range. Just take a read through, and "it will be obvious to the casual observer..." (as my first C++ instructor loved to say /grin/).

    I've also included two GM console buttons to toggle the orbital movement, and (wait for it....) to toggle moving the entire system along a path. Yup -- the whole thing travels. Just a linear path along X axis in this example, but it's easy to find the location in the code where the path is determined and you could change the path to be anything that suits your scenario script.

    I hope you find it useful, or at least mildly entertaining, ha.

    Happy orbiting! Enjoy!

    Drat!
    Script was too long to post here! Ok, here's a link to the script file:

    https://drive.google.com/open?id=1eMlqXe6NrEKbZcbL5bB81T0AoRQ2reF6

    If that doesn't work for some reason in the future, msg me and I'll get you a link.
  • Makes my stuff looks so hap-hazard :) Well done you. Going to totally steal this.
  • Quick Question Kilted, Using the Whirlpool one, is there an easy way to convert to effect ALL objects.

    Looking at a For loop effecting all object but wondering how you would approach it?
  • Greetings Dwaine!

    My sincere apologies for my absence. I had to go on an unexpected trip a few weeks back and then there was the joyous crush of Christmas. So again, my apologies.

    Ref your question regarding the whirlpool effect, yes! Depending on the scope of the space objects you want to have affected by the gravitational pull of the black hole, here's how I would approach it:

    -- in the init() function, put everything you want to have affected by the BH into a multi-dimensional array; the first element in the first array is (of course) the second array, then the elements in the second array will be 1) the space object that will spiral, 2) it's angular location of the object to the BH, 3) the angular speed at which the item is spiraling towards the BH, 4) the radial speed at which the item is approaching the the BH
    -- in the update() function, you can use a for loop to iterate through the multi-dimensional array (the ipairs function works great here) and make all the updates to the space objects depending on their angular and radial speeds

    The whirlpool code example shows how to work through the math decrements to get the space object to spiral into the BH.

    If you look in my most previous orbital example ("scenario_xx_blackhold_orbital_debris.lua"), I use several multidimensional arrays. Just in case you need it, here's the Lua reference link: https://www.lua.org/pil/11.2.html

    Funny, but I mention in the post above that I was planning to use the whirlpool function to implement a larger environment idea where the BH is leeching off a nearby star. The effect would generally be that the large radius star (20000?) is throwing off nebula which get immediately caught up into the BH gravitational pull and then sucked in! And of course it wouldn't be just a single line of nebula, but more like a "V" coming off the star and then condensing to a thick stream into the BH.

    Again, sorry for the break!
Sign In or Register to comment.