206 lines
7.1 KiB
GDScript
206 lines
7.1 KiB
GDScript
class_name StarSystemGenerator
|
|
extends Node2D
|
|
|
|
# Number of bodies to generate for each type.
|
|
@export var num_planets: int = 5
|
|
@export var num_moons_per_planet: int = 2
|
|
@export var num_stations: int = 3
|
|
|
|
|
|
# Exported scenes to be instantiated. Drag and drop the scene files
|
|
# for each body from the Godot FileSystem dock into these properties.
|
|
@export var star_scene: PackedScene
|
|
@export var planet_scene: PackedScene
|
|
@export var moon_scene: PackedScene
|
|
@export var station_scene: PackedScene
|
|
@export var asteroid_scene: PackedScene
|
|
|
|
# --- Simulation Parameters ---
|
|
@export var sim_scale: float = 1e+9 # A scale of 1 unit per 1 billion meters.
|
|
|
|
# --- Star Parameters ---
|
|
# Increasing the star's mass to increase overall gravitational influence.
|
|
const STAR_MASS_REAL = 1.989e+30 # Mass of the Sun in kg.
|
|
const STAR_RADIUS = 50.0
|
|
|
|
# --- Planet Parameters ---
|
|
# Increasing the distances to give planets more space and allow for higher velocities.
|
|
const PLANET_DISTANCE_MIN = 50.0 * 1.5e+10 # 50 AU
|
|
const PLANET_DISTANCE_MAX = 500.0 * 1.5e+10 # 500 AU
|
|
const PLANET_COUNT_MIN = 3
|
|
const PLANET_COUNT_MAX = 8
|
|
|
|
# --- Moon Parameters ---
|
|
const MOON_DISTANCE_MIN = 2e8 # 20,000 km
|
|
const MOON_DISTANCE_MAX = 3e9 # 100,000 km
|
|
const MOON_COUNT_MIN = 0
|
|
const MOON_COUNT_MAX = 4
|
|
|
|
# --- Asteroid Parameters ---
|
|
# Minimum and maximum number of asteroids to generate.
|
|
@export var MIN_ASTEROIDS: int = 50
|
|
@export var MAX_ASTEROIDS: int = 200
|
|
|
|
const ASTEROID_DISTANCE_MIN = 3.2e11
|
|
const ASTEROID_DISTANCE_MAX = 4.8e11
|
|
|
|
# --- Station Parameters ---
|
|
const STATION_COUNT_MIN = 1
|
|
const STATION_COUNT_MAX = 3
|
|
|
|
var star: CelestialBody
|
|
var planets: Array
|
|
var moons: Array
|
|
var asteroids: Array
|
|
var stations: Array
|
|
|
|
const NAME_TEMPLATE_STR = "%s_%s"
|
|
|
|
func _ready() -> void:
|
|
generate_star_system()
|
|
|
|
func generate_star_system() -> void:
|
|
randomize()
|
|
|
|
star = create_star()
|
|
add_child(star)
|
|
|
|
planets = create_planets(star)
|
|
for planet in planets:
|
|
add_child(planet)
|
|
|
|
asteroids = create_asteroids(star)
|
|
for asteroid in asteroids:
|
|
add_child(asteroid)
|
|
|
|
stations = create_stations(star)
|
|
for station in stations:
|
|
add_child(station)
|
|
|
|
func get_all_bodies() -> Array:
|
|
var all_bodies = []
|
|
all_bodies.append(star)
|
|
all_bodies.append_array(planets)
|
|
all_bodies.append_array(asteroids)
|
|
all_bodies.append_array(stations)
|
|
all_bodies.append_array(moons)
|
|
return all_bodies
|
|
|
|
func create_star() -> CelestialBody:
|
|
var star_instance = star_scene.instantiate() as CelestialBody
|
|
star_instance.position = Vector2.ZERO
|
|
star_instance.mass_real = STAR_MASS_REAL
|
|
star_instance.radius = STAR_RADIUS
|
|
star_instance.sim_scale = sim_scale
|
|
return star_instance
|
|
|
|
func create_planets(primary_body: CelestialBody) -> Array:
|
|
var planets = []
|
|
var planet_count = randi_range(PLANET_COUNT_MIN, PLANET_COUNT_MAX)
|
|
for i in range(planet_count):
|
|
var planet_instance = planet_scene.instantiate() as CelestialBody
|
|
planet_instance.name = NAME_TEMPLATE_STR % [planet_instance.get_class_name(), i]
|
|
planet_instance.primary = primary_body
|
|
planet_instance.mass_real = randf_range(5.972e+24, 6.39e+26) # Earth to Saturn mass
|
|
planet_instance.radius = randf_range(30.0, 80.0)
|
|
planet_instance.sim_scale = sim_scale
|
|
|
|
var distance_real = randf_range(PLANET_DISTANCE_MIN, PLANET_DISTANCE_MAX)
|
|
var distance_scaled = distance_real / sim_scale
|
|
|
|
var velocity_scaled = planet_instance.get_stable_orbit_velocity(primary_body.mass_real, distance_real)
|
|
var orbit_angle = randf_range(0.0, PI * 2)
|
|
|
|
planet_instance.position.x = distance_scaled * cos(orbit_angle)
|
|
planet_instance.position.y = distance_scaled * sin(orbit_angle)
|
|
|
|
planet_instance.linear_velocity = Vector2(0, velocity_scaled).rotated(orbit_angle + PI / 2.0)
|
|
|
|
planets.append(planet_instance)
|
|
|
|
var planet_moons = create_moons(planet_instance)
|
|
for moon in planet_moons:
|
|
planet_instance.add_child(moon)
|
|
moons.append(moon)
|
|
|
|
return planets
|
|
|
|
func create_moons(primary_body: CelestialBody) -> Array:
|
|
var moons = []
|
|
var moon_count = randi_range(MOON_COUNT_MIN, MOON_COUNT_MAX)
|
|
for i in range(moon_count):
|
|
var moon_instance = moon_scene.instantiate() as CelestialBody
|
|
moon_instance.name = NAME_TEMPLATE_STR % [moon_instance.get_class_name(), i]
|
|
moon_instance.primary = primary_body
|
|
moon_instance.mass_real = randf_range(7.342e+22, 1.48e+23) # Moon to Triton mass
|
|
moon_instance.radius = randf_range(10.0, 20.0)
|
|
moon_instance.sim_scale = sim_scale
|
|
|
|
var distance_real = randf_range(MOON_DISTANCE_MIN, MOON_DISTANCE_MAX)
|
|
var distance_scaled = distance_real / sim_scale
|
|
|
|
var velocity_scaled = moon_instance.get_stable_orbit_velocity(primary_body.mass_real, distance_real)
|
|
var orbit_angle = randf_range(0.0, PI * 2)
|
|
|
|
moon_instance.position.x = primary_body.position.x + distance_scaled * cos(orbit_angle)
|
|
moon_instance.position.y = primary_body.position.y + distance_scaled * sin(orbit_angle)
|
|
|
|
moon_instance.linear_velocity = primary_body.linear_velocity + Vector2(0, velocity_scaled).rotated(orbit_angle + PI / 2.0)
|
|
|
|
moons.append(moon_instance)
|
|
|
|
return moons
|
|
|
|
func create_asteroids(primary_body: CelestialBody) -> Array:
|
|
var asteroids = []
|
|
var asteroid_count = randi_range(MIN_ASTEROIDS, MAX_ASTEROIDS)
|
|
|
|
for i in range(asteroid_count):
|
|
var asteroid_instance = asteroid_scene.instantiate() as CelestialBody
|
|
asteroid_instance.name = NAME_TEMPLATE_STR % [asteroid_instance.get_class_name(), i]
|
|
asteroid_instance.primary = primary_body
|
|
asteroid_instance.mass_real = randf_range(1e+12, 1e+16) # A realistic asteroid mass range
|
|
asteroid_instance.radius = randf_range(2.0, 8.0)
|
|
asteroid_instance.sim_scale = sim_scale
|
|
|
|
var distance_real = randf_range(ASTEROID_DISTANCE_MIN, ASTEROID_DISTANCE_MAX)
|
|
var distance_scaled = distance_real / sim_scale
|
|
|
|
var velocity_scaled = asteroid_instance.get_stable_orbit_velocity(primary_body.mass_real, distance_real)
|
|
var orbit_angle = randf_range(0.0, PI * 2)
|
|
|
|
asteroid_instance.position.x = distance_scaled * cos(orbit_angle)
|
|
asteroid_instance.position.y = distance_scaled * sin(orbit_angle)
|
|
|
|
asteroid_instance.linear_velocity = Vector2(0, velocity_scaled).rotated(orbit_angle + PI / 2.0)
|
|
|
|
asteroids.append(asteroid_instance)
|
|
|
|
return asteroids
|
|
|
|
func create_stations(primary_body: CelestialBody) -> Array:
|
|
var stations = []
|
|
var station_count = randi_range(STATION_COUNT_MIN, STATION_COUNT_MAX)
|
|
for i in range(station_count):
|
|
var station_instance = station_scene.instantiate() as CelestialBody
|
|
station_instance.name = NAME_TEMPLATE_STR % [station_instance.get_class_name(), i]
|
|
station_instance.primary = primary_body
|
|
station_instance.mass_real = randf_range(5e+5, 1e+6) # Realistic mass for a large space station
|
|
station_instance.radius = randf_range(15.0, 25.0)
|
|
station_instance.sim_scale = sim_scale
|
|
|
|
var distance_real = randf_range(PLANET_DISTANCE_MIN, PLANET_DISTANCE_MAX)
|
|
var distance_scaled = distance_real / sim_scale
|
|
|
|
var velocity_scaled = station_instance.get_stable_orbit_velocity(primary_body.mass_real, distance_real)
|
|
var orbit_angle = randf_range(0.0, PI * 2)
|
|
|
|
station_instance.position.x = distance_scaled * cos(orbit_angle)
|
|
station_instance.position.y = distance_scaled * sin(orbit_angle)
|
|
|
|
station_instance.linear_velocity = Vector2(0, velocity_scaled).rotated(orbit_angle + PI / 2.0)
|
|
|
|
stations.append(station_instance)
|
|
|
|
return stations
|