Files
millimeters-of-aluminum/scripts/star_system_generator.gd
olof.pettersson 99e032f303 initial commit
2025-09-12 15:54:10 +02:00

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