Scaled down simulation
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
# Godot 4+ specific ignores
|
||||
.godot/
|
||||
.vscode/
|
||||
/android/
|
||||
|
||||
/addons/
|
||||
@ -11,13 +11,17 @@
|
||||
|
||||
[node name="Node2D" type="Node2D"]
|
||||
script = ExtResource("1_h2yge")
|
||||
min_asteroid_belts = 0
|
||||
min_planets = 1
|
||||
max_planets = 4
|
||||
max_moons = 10
|
||||
max_asteroid_belts = 2
|
||||
max_star_stations = 0
|
||||
star_scene = ExtResource("2_7mycd")
|
||||
planet_scene = ExtResource("3_272bh")
|
||||
moon_scene = ExtResource("4_5vw27")
|
||||
station_scene = ExtResource("5_kek77")
|
||||
asteroid_scene = ExtResource("6_4c57u")
|
||||
sim_scale = 1e+09
|
||||
sim_scale = 0.21
|
||||
|
||||
[node name="DeveloperPawn" parent="." node_paths=PackedStringArray("map_canvas") instance=ExtResource("7_272bh")]
|
||||
input_pickable = true
|
||||
|
||||
27
main.tscn6546160625.tmp
Normal file
27
main.tscn6546160625.tmp
Normal file
@ -0,0 +1,27 @@
|
||||
[gd_scene load_steps=9 format=3 uid="uid://dogqi2c58qdc0"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://j3j483itissq" path="res://scripts/star_system_generator.gd" id="1_h2yge"]
|
||||
[ext_resource type="PackedScene" uid="uid://5uqp4amjj7ww" path="res://scenes/star.tscn" id="2_7mycd"]
|
||||
[ext_resource type="PackedScene" uid="uid://clt4qlsjcfgln" path="res://scenes/planet.tscn" id="3_272bh"]
|
||||
[ext_resource type="PackedScene" uid="uid://74ppvxcw8an4" path="res://scenes/moon.tscn" id="4_5vw27"]
|
||||
[ext_resource type="PackedScene" uid="uid://dm3s33o4xhqfv" path="res://scenes/station.tscn" id="5_kek77"]
|
||||
[ext_resource type="PackedScene" uid="uid://bawsujtlpmh5r" path="res://scenes/asteroid.tscn" id="6_4c57u"]
|
||||
[ext_resource type="PackedScene" uid="uid://cm5qsuunboxm3" path="res://scenes/developer_pawn.tscn" id="7_272bh"]
|
||||
[ext_resource type="PackedScene" uid="uid://ctlw5diis8h1x" path="res://scenes/map_canvas.tscn" id="8_5vw27"]
|
||||
|
||||
[node name="Node2D" type="Node2D"]
|
||||
script = ExtResource("1_h2yge")
|
||||
min_asteroid_belts = 0
|
||||
star_scene = ExtResource("2_7mycd")
|
||||
planet_scene = ExtResource("3_272bh")
|
||||
moon_scene = ExtResource("4_5vw27")
|
||||
station_scene = ExtResource("5_kek77")
|
||||
asteroid_scene = ExtResource("6_4c57u")
|
||||
sim_scale = 1e+09
|
||||
|
||||
[node name="DeveloperPawn" parent="." node_paths=PackedStringArray("map_canvas") instance=ExtResource("7_272bh")]
|
||||
input_pickable = true
|
||||
map_canvas = NodePath("../MapCanvas")
|
||||
|
||||
[node name="MapCanvas" parent="." node_paths=PackedStringArray("star_system_generator") instance=ExtResource("8_5vw27")]
|
||||
star_system_generator = NodePath("..")
|
||||
@ -10,7 +10,7 @@ func get_class_name() -> String:
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
# An Asteroid has negligible mass for physics calculations.
|
||||
mass = 0.001
|
||||
#mass = 0.001
|
||||
radius = 5.0
|
||||
|
||||
# You can set a default texture here.
|
||||
|
||||
@ -5,7 +5,7 @@ extends RigidBody2D
|
||||
@export var primary: CelestialBody
|
||||
|
||||
# Real-world gravitational constant.
|
||||
const G_REAL = 6.674e-11
|
||||
const G = 0.0001
|
||||
|
||||
# This is a placeholder for your pixel art texture.
|
||||
@export var texture: Texture2D
|
||||
@ -13,8 +13,6 @@ const G_REAL = 6.674e-11
|
||||
# The radius of the body, used for drawing and future collision detection.
|
||||
@export var radius: float = 10.0
|
||||
|
||||
# Real-world mass of the body in kilograms.
|
||||
@export_range(1.0, 1.989e+30, 1.0, "exp") var mass_real: float = 1.0
|
||||
|
||||
# The scaling factor for the simulation. A value of 1.0 means no scaling.
|
||||
var sim_scale: float = 1.0
|
||||
@ -27,6 +25,7 @@ var orbit_radius_real : float = 0.0
|
||||
var linear_velocity_real : Vector2 = Vector2.ZERO
|
||||
var global_position_real : Vector2 = Vector2.ZERO
|
||||
var current_central_force_real : Vector2 = Vector2.ZERO
|
||||
var direction_to_primary : Vector2 = Vector2.ZERO
|
||||
|
||||
func get_class_name() -> String:
|
||||
return "CelestialBody"
|
||||
@ -34,13 +33,17 @@ func get_class_name() -> String:
|
||||
func _ready() -> void:
|
||||
# Set the scaled mass based on the real-world mass and the simulation scale.
|
||||
# The scale is applied to the mass, so a smaller scale means a larger apparent mass.
|
||||
mass = mass_real / sim_scale
|
||||
|
||||
# We will handle gravity manually, so we set the built-in gravity scale to 0.
|
||||
gravity_scale = 0.0
|
||||
|
||||
# To make the simulation work without drag, we must set linear damping to 0.
|
||||
linear_damp = 0.0
|
||||
angular_damp = 0.0
|
||||
|
||||
can_sleep = false
|
||||
|
||||
custom_integrator = true
|
||||
|
||||
# Set the color based on the class name for easy differentiation.
|
||||
match get_class_name():
|
||||
@ -58,24 +61,24 @@ func _ready() -> void:
|
||||
body_color = Color.ORANGE_RED
|
||||
|
||||
|
||||
var is_first_integration : bool = true
|
||||
|
||||
# This callback is the correct place to apply custom forces to a RigidBody2D.
|
||||
func _integrate_forces(state: PhysicsDirectBodyState2D) -> void:
|
||||
if primary and is_instance_valid(primary):
|
||||
# Get the vector pointing from this body to its primary.
|
||||
var direction_to_primary = primary.global_position_real - global_position_real
|
||||
var distance_squared = direction_to_primary.length_squared()
|
||||
#print(distance_squared / (sim_scale * sim_scale))
|
||||
direction_to_primary = self.global_position.direction_to(primary.global_position)
|
||||
var distance_squared = self.global_position.distance_squared_to(primary.global_position)
|
||||
# Prevent division by zero or a large force if bodies are on top of each other.
|
||||
if distance_squared > 1.0:
|
||||
# Calculate the magnitude of the gravitational force using Newton's law.
|
||||
# We now use the scaled masses, which is consistent with Godot's physics engine.
|
||||
# F = G * (m1 * m2) / r^2
|
||||
var force_magnitude = ((G_REAL) * self.mass_real * primary.mass_real) / (distance_squared)
|
||||
var force_magnitude = (G * self.mass * primary.mass) / (distance_squared)
|
||||
|
||||
# Apply the force in the direction of the primary.
|
||||
current_central_force_real = (direction_to_primary.normalized() * force_magnitude)
|
||||
state.apply_central_force(current_central_force_real / sim_scale)
|
||||
|
||||
current_central_force_real = (direction_to_primary * force_magnitude)
|
||||
state.apply_central_force(current_central_force_real)
|
||||
|
||||
# We force a redraw here to update the body's visual representation.
|
||||
queue_redraw()
|
||||
@ -94,14 +97,16 @@ func _draw() -> void:
|
||||
|
||||
|
||||
func calculate_initial_orbit_real(primary: CelestialBody, orbiter : CelestialBody):
|
||||
print("Orbital velocity for: " + str(orbiter))
|
||||
# The formula for real-world orbital velocity is v = sqrt(G * M / r)
|
||||
var magnitude = sqrt((G_REAL * primary.mass_real) / primary.global_position_real.distance_to(orbiter.global_position_real))
|
||||
|
||||
var magnitude = sqrt(G * (primary.mass) / primary.global_position.distance_to(orbiter.global_position))
|
||||
print(magnitude)
|
||||
# Calculate the relative position vector from the star to the body
|
||||
var unit_vector = primary.global_position_real.direction_to(orbiter.global_position_real)
|
||||
|
||||
var unit_vector = primary.global_position.direction_to(orbiter.global_position)
|
||||
print(unit_vector)
|
||||
# Calculate a perpendicular vector (swapping and negating components)
|
||||
var orbit_direction = Vector2(unit_vector.y, -unit_vector.x)
|
||||
|
||||
print(orbit_direction)
|
||||
|
||||
# Scale this velocity down to the simulation scale before returning.
|
||||
return orbit_direction * magnitude
|
||||
return orbit_direction * magnitude + primary.linear_velocity
|
||||
|
||||
@ -1,104 +1,163 @@
|
||||
class_name MapDrawer
|
||||
extends Node2D
|
||||
|
||||
# A reference to the StarSystemGenerator node, which will be set by the MapCanvas.
|
||||
var star_system_generator: StarSystemGenerator
|
||||
# The body at the center of the map view.
|
||||
var focal_body: CelestialBody
|
||||
# The list of bodies to be rendered in the current view.
|
||||
var bodies_to_draw: Array[CelestialBody] = []
|
||||
# The scale used for drawing, stored to be accessible by the input handler.
|
||||
var draw_scale: float = 1.0
|
||||
|
||||
# A reference to the generator, with a setter to initialize the view.
|
||||
var star_system_generator: StarSystemGenerator:
|
||||
set(value):
|
||||
star_system_generator = value
|
||||
# When the reference is set, initialize the view on the star.
|
||||
if star_system_generator and star_system_generator.has_generated:
|
||||
set_view(star_system_generator.get_system_data().star)
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
# This forces the canvas to redraw every frame.
|
||||
if not focal_body:
|
||||
set_view(star_system_generator.get_system_data().star)
|
||||
|
||||
queue_redraw()
|
||||
|
||||
func _draw() -> void:
|
||||
if not star_system_generator:
|
||||
# --- Main Public Method ---
|
||||
|
||||
# Sets the view to a new central body and rebuilds the list of what to draw.
|
||||
func set_view(new_focal_body: CelestialBody) -> void:
|
||||
if not is_instance_valid(new_focal_body):
|
||||
return
|
||||
|
||||
focal_body = new_focal_body
|
||||
bodies_to_draw.clear()
|
||||
|
||||
# Draw a black background to obscure the main simulation view.
|
||||
var viewport_size = get_viewport().get_visible_rect().size
|
||||
draw_rect(Rect2(Vector2.ZERO, viewport_size), Color("000000"))
|
||||
# The view always includes the focal body.
|
||||
bodies_to_draw.append(focal_body)
|
||||
|
||||
# Add all direct children that are celestial bodies.
|
||||
for child in focal_body.get_children():
|
||||
if child is CelestialBody:
|
||||
bodies_to_draw.append(child)
|
||||
|
||||
# If the star is the focus, also find and draw the asteroid belts.
|
||||
if focal_body is Star:
|
||||
var system_data = star_system_generator.get_system_data()
|
||||
for belt in system_data.belts:
|
||||
# We'll handle drawing belts separately in the _draw function.
|
||||
pass
|
||||
|
||||
|
||||
# --- Input Handling ---
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if not focal_body:
|
||||
return
|
||||
|
||||
# Handle Zoom In with Left Click
|
||||
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed():
|
||||
for body in bodies_to_draw:
|
||||
# Calculate the body's position on screen for hit-testing.
|
||||
var relative_pos = body.global_position - focal_body.global_position
|
||||
var scaled_pos = relative_pos * draw_scale + get_viewport_center()
|
||||
var radius = _get_body_draw_radius(body)
|
||||
|
||||
if event.position.distance_to(scaled_pos) < radius * 2.0: # A larger click target
|
||||
set_view(body)
|
||||
get_viewport().set_input_as_handled()
|
||||
return
|
||||
|
||||
# Handle Zoom Out with Right Click
|
||||
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT and event.is_pressed():
|
||||
if is_instance_valid(focal_body.primary):
|
||||
set_view(focal_body.primary)
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
# --- Drawing Logic ---
|
||||
|
||||
func _draw() -> void:
|
||||
# [cite_start]Draw a black background. [cite: 4]
|
||||
draw_rect(Rect2(Vector2.ZERO, get_viewport_size()), Color.BLACK)
|
||||
|
||||
if not is_instance_valid(focal_body):
|
||||
focal_body = star_system_generator.get_system_data().star
|
||||
return
|
||||
|
||||
# 1. Determine the scale for the current view.
|
||||
var max_distance = 0.0
|
||||
var system_data = star_system_generator.get_system_data()
|
||||
var all_bodies = system_data.all_bodies()
|
||||
|
||||
# Find the furthest body from the star.
|
||||
for body in all_bodies:
|
||||
var distance = body.global_position.length()
|
||||
#print(body)
|
||||
for body in bodies_to_draw:
|
||||
if body == focal_body: continue
|
||||
var distance = body.global_position.distance_to(focal_body.global_position)
|
||||
if distance > max_distance:
|
||||
max_distance = distance
|
||||
|
||||
# Determine the scale based on the viewport size.
|
||||
# Add a default zoom level if focused on a body with no children.
|
||||
if max_distance == 0.0:
|
||||
max_distance = 5.0e8 # An arbitrary distance for a nice solo view.
|
||||
|
||||
var system_diameter = max_distance * 2.0
|
||||
var draw_scale = min(viewport_size.x, viewport_size.y) / system_diameter
|
||||
draw_scale *= 0.8 # Add some padding to the view.
|
||||
draw_scale = min(get_viewport_size().x, get_viewport_size().y) / system_diameter
|
||||
draw_scale *= 0.8 # Add some padding.
|
||||
|
||||
for belt in system_data.belts:
|
||||
var scaled_radius = Vector2(belt.centered_radius, 0.0) * draw_scale + viewport_size / 2
|
||||
draw_circle(viewport_size / 2, (scaled_radius - viewport_size / 2).length(), Color.WHITE, false, 1.0)
|
||||
#draw_string(ThemeDB.fallback_font, scaled_position + Vector2(radius + 2, -5), "Asteroid Belt", HORIZONTAL_ALIGNMENT_LEFT, -1, ThemeDB.fallback_font_size, Color.WHITE)
|
||||
|
||||
# Draw each celestial body on the canvas.
|
||||
for body in all_bodies:
|
||||
# Get the scaled position.
|
||||
var scaled_position = body.global_position * draw_scale + viewport_size / 2
|
||||
|
||||
# Define visual size based on body type.
|
||||
var radius = 0.0
|
||||
var color = Color.WHITE
|
||||
|
||||
match body.get_class_name():
|
||||
"Star":
|
||||
color = Color.GOLD
|
||||
"Planet":
|
||||
color = Color.BLUE
|
||||
"Moon":
|
||||
color = Color.PURPLE
|
||||
"Station":
|
||||
color = Color.WHITE
|
||||
"Asteroid":
|
||||
color = Color.BROWN
|
||||
_:
|
||||
color = Color.ORANGE_RED
|
||||
# 2. Draw asteroid belts if the star is the focus.
|
||||
if focal_body is Star:
|
||||
for belt in star_system_generator.get_system_data().belts:
|
||||
var relative_radius = belt.centered_radius - focal_body.global_position.length()
|
||||
var scaled_radius = relative_radius * draw_scale
|
||||
draw_circle(get_viewport_center(), scaled_radius, Color.WHITE, false)
|
||||
|
||||
if body is Star:
|
||||
radius = 10.0 # Make the star smaller for the map.
|
||||
elif body is Planet:
|
||||
radius = 8.0
|
||||
elif body is Moon:
|
||||
radius = 5.0
|
||||
elif body is Asteroid:
|
||||
radius = 4.0 # Make asteroids bigger for visibility.
|
||||
elif body is Station:
|
||||
radius = 6.0
|
||||
|
||||
# Draw the celestial body.
|
||||
if body is Planet or body is Moon or body is Station:
|
||||
draw_string(ThemeDB.fallback_font, scaled_position + Vector2(radius + 2, -5), body.name, HORIZONTAL_ALIGNMENT_LEFT, -1, ThemeDB.fallback_font_size, color)
|
||||
draw_circle(viewport_size / 2, (scaled_position - viewport_size / 2).length(), Color.WHITE, false, 1.0)
|
||||
|
||||
draw_circle(scaled_position, radius, color)
|
||||
# 3. Draw each celestial body relative to the focal body.
|
||||
for body in bodies_to_draw:
|
||||
var relative_pos = body.global_position - focal_body.global_position
|
||||
var scaled_pos = relative_pos * draw_scale + get_viewport_center()
|
||||
|
||||
draw_string(ThemeDB.fallback_font, Vector2.ZERO + Vector2(10, 15), str(Engine.time_scale), HORIZONTAL_ALIGNMENT_LEFT, -1, ThemeDB.fallback_font_size, Color.HOT_PINK)
|
||||
var radius = _get_body_draw_radius(body)
|
||||
var color = _get_body_draw_color(body)
|
||||
|
||||
var velocity: Vector2 = body.linear_velocity * draw_scale
|
||||
var force: Vector2 = body.current_central_force_real * draw_scale / body.sim_scale
|
||||
# Draw orbit line for all children
|
||||
if body != focal_body and body is not Asteroid:
|
||||
draw_circle(get_viewport_center(), scaled_pos.distance_to(get_viewport_center()), Color(Color.WHITE, 0.2), false)
|
||||
draw_string(ThemeDB.fallback_font, scaled_pos + Vector2(radius + 5, 5), body.name, HORIZONTAL_ALIGNMENT_LEFT, -1, ThemeDB.fallback_font_size, color)
|
||||
|
||||
# Draw the body itself.
|
||||
draw_circle(scaled_pos, radius, color)
|
||||
|
||||
# Draw velocity and force vectors.
|
||||
var velocity: Vector2 = body.linear_velocity.normalized() * 25.0
|
||||
var force: Vector2 = body.direction_to_primary * 25.0 # Normalize force for consistent arrow size
|
||||
|
||||
draw_arrow(scaled_pos, scaled_pos + velocity, Color.GREEN)
|
||||
draw_arrow(scaled_pos, scaled_pos + force, Color.RED)
|
||||
|
||||
# --- Helper Functions ---
|
||||
|
||||
func get_viewport_size() -> Vector2:
|
||||
return get_viewport().get_visible_rect().size
|
||||
|
||||
func get_viewport_center() -> Vector2:
|
||||
return get_viewport_size() / 2.0
|
||||
|
||||
func _get_body_draw_radius(body: CelestialBody) -> float:
|
||||
if body is Star: return 15.0
|
||||
elif body is Planet: return 10.0
|
||||
elif body is Moon: return 6.0
|
||||
elif body is Station: return 7.0
|
||||
elif body is Asteroid: return 4.0
|
||||
return 5.0
|
||||
|
||||
func _get_body_draw_color(body: CelestialBody) -> Color:
|
||||
match body.get_class_name():
|
||||
"Star": return Color.GOLD
|
||||
"Planet": return Color.BLUE
|
||||
"Moon": return Color.PURPLE
|
||||
"Station": return Color.WHITE
|
||||
"Asteroid": return Color.BROWN
|
||||
return Color.ORANGE_RED
|
||||
|
||||
# Draw the velocity arrow
|
||||
#
|
||||
## Draw the force arrow
|
||||
draw_arrow(scaled_position, scaled_position + force, Color(1, 0, 0))
|
||||
draw_arrow(scaled_position, scaled_position + velocity, Color(0, 1, 0))
|
||||
|
||||
func draw_arrow(start: Vector2, end: Vector2, color: Color):
|
||||
var head_size = max(1, (end - start).length() / 50) # Adjust the divisor for desired size
|
||||
var direction = (end - start).normalized()
|
||||
draw_line(start, end, color, 2.0)
|
||||
var dir = (end - start).normalized()
|
||||
var p1 = end - dir * 8 + dir.orthogonal() * 5
|
||||
var p2 = end - dir * 8 - dir.orthogonal() * 5
|
||||
draw_polygon(PackedVector2Array([end, p1, p2]), PackedColorArray([color, color, color]))
|
||||
|
||||
# Draw the line
|
||||
draw_line(start, end, color)
|
||||
|
||||
# Draw the triangular arrowhead at the tip
|
||||
var points = PackedVector2Array()
|
||||
points.push_back(end)
|
||||
points.push_back(end - direction * head_size + Vector2(-head_size, head_size))
|
||||
points.push_back(end - direction * head_size + Vector2(-head_size, -head_size))
|
||||
draw_polygon(points, PackedColorArray([color]))
|
||||
|
||||
@ -10,7 +10,7 @@ func get_class_name() -> String:
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
# A Moon has a smaller mass than a planet.
|
||||
mass = 100.0
|
||||
#mass = 100.0
|
||||
radius = 10.0
|
||||
|
||||
# You can set a default texture here.
|
||||
|
||||
@ -10,7 +10,7 @@ func get_class_name() -> String:
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
# A Planet has a smaller mass than a star.
|
||||
mass = 1000.0
|
||||
#mass = 1000.0
|
||||
radius = 25.0
|
||||
|
||||
# You can set a default texture here.
|
||||
|
||||
@ -8,7 +8,6 @@ func get_class_name() -> String:
|
||||
func _ready() -> void:
|
||||
# A Star has no primary and a very large mass.
|
||||
primary = null
|
||||
mass = 100000.0
|
||||
radius = 50.0
|
||||
|
||||
# You can set a default texture here, or assign it in the Inspector.
|
||||
|
||||
@ -32,13 +32,15 @@ extends Node2D
|
||||
# A scaling parameter to convert real-world units to game units.
|
||||
# 1 meter = sim_scale game units.
|
||||
@export_group("Simulation Scale")
|
||||
@export var sim_scale: float = 1.0e-9
|
||||
@export_range(10e-12, 1.0, 10.e-3) var sim_scale: float = 1.0e-6
|
||||
|
||||
# A factor to scale the initial orbital distances to make the system visually compelling.
|
||||
@export var min_ring_distance: float = 2.0e10
|
||||
@export var min_ring_distance: float = 500
|
||||
@export var min_planetary_orbit_radius : float = 50
|
||||
|
||||
# A factor to determine the buffer between orbits based on mass.
|
||||
@export var orbit_buffer_factor: float = 1
|
||||
const orbit_buffer_constant : float = 1.0e-13
|
||||
const orbit_buffer_constant : float = 300
|
||||
var orbit_buffer : float = orbit_buffer_constant * orbit_buffer_factor
|
||||
|
||||
# A flag to check if the system has been generated.
|
||||
@ -46,7 +48,12 @@ var has_generated: bool = false
|
||||
|
||||
# Constants for real-world physics calculations.
|
||||
const G = 6.67430e-11 # Gravitational constant (N·m²/kg²)
|
||||
const SUN_MASS = 1.989e30 # Mass of the sun (kg)
|
||||
#const SUN_MASS = 1.989e30 # Mass of the sun (kg)
|
||||
const SUN_MASS = 10.000
|
||||
const PLANETARY_MASS = SUN_MASS / 10
|
||||
const MOON_MASS = PLANETARY_MASS / 10
|
||||
const ASTEROID_MASS = MOON_MASS / 10
|
||||
const STATION_MASS = ASTEROID_MASS / 10
|
||||
|
||||
var system_data : SystemData
|
||||
|
||||
@ -61,6 +68,8 @@ func generate_star_system() -> void:
|
||||
# Create the star at the center of the system.
|
||||
var star_instance = _create_star()
|
||||
|
||||
add_child(star_instance)
|
||||
|
||||
# Generate and place all celestial bodies in randomized order.
|
||||
_generate_and_place_bodies(star_instance)
|
||||
|
||||
@ -69,12 +78,11 @@ func _create_star() -> RigidBody2D:
|
||||
var star_instance = star_scene.instantiate() as Star
|
||||
system_data.star = star_instance
|
||||
star_instance.name = "Star"
|
||||
add_child(star_instance)
|
||||
star_instance.sim_scale = sim_scale
|
||||
|
||||
# Set the star's properties.
|
||||
star_instance.orbit_radius_real = 0.0
|
||||
star_instance.mass_real = SUN_MASS
|
||||
star_instance.mass = SUN_MASS
|
||||
star_instance.linear_velocity_real = Vector2.ZERO
|
||||
star_instance.modulate = Color("ffe066") # Yellow
|
||||
|
||||
@ -112,15 +120,15 @@ func _generate_and_place_bodies(primary: RigidBody2D) -> void:
|
||||
planet_instance.name = "Planet " + str(current_orbit_radius)
|
||||
planet_instance.primary = primary
|
||||
planet_instance.sim_scale = sim_scale
|
||||
planet_instance.mass_real = randf_range(1e24, 1e25)
|
||||
planet_instance.mass = PLANETARY_MASS # randf_range(1e24, 1e25)
|
||||
|
||||
# Calculate orbit based on the last placed body.
|
||||
planet_instance.orbit_radius_real = current_orbit_radius + (planet_instance.mass_real * orbit_buffer)
|
||||
planet_instance.orbit_radius_real = current_orbit_radius + (planet_instance.mass * orbit_buffer)
|
||||
|
||||
_create_body_in_ring(primary, planet_instance)
|
||||
_create_moons_and_stations(planet_instance)
|
||||
|
||||
current_orbit_radius = planet_instance.orbit_radius_real + (planet_instance.mass_real * orbit_buffer)
|
||||
current_orbit_radius = planet_instance.orbit_radius_real + (planet_instance.mass * orbit_buffer)
|
||||
|
||||
"asteroid_belt":
|
||||
var belt = _create_asteroid_belt(primary, current_orbit_radius)
|
||||
@ -134,38 +142,40 @@ func _generate_and_place_bodies(primary: RigidBody2D) -> void:
|
||||
station_instance.name = "Star Station " + str(current_orbit_radius)
|
||||
station_instance.primary = primary
|
||||
station_instance.sim_scale = sim_scale
|
||||
station_instance.mass_real = 1e8 # A very small mass
|
||||
station_instance.mass = STATION_MASS # A very small mass
|
||||
|
||||
station_instance.orbit_radius_real = current_orbit_radius + (station_instance.mass_real * orbit_buffer)
|
||||
station_instance.orbit_radius_real = current_orbit_radius + (station_instance.mass * orbit_buffer)
|
||||
|
||||
_create_body_in_ring(primary, station_instance)
|
||||
|
||||
current_orbit_radius = station_instance.orbit_radius_real + (station_instance.mass_real * orbit_buffer)
|
||||
current_orbit_radius = station_instance.orbit_radius_real + (station_instance.mass * orbit_buffer)
|
||||
|
||||
print("Star system generation complete.")
|
||||
|
||||
# Creates moons and stations around a primary body.
|
||||
func _create_moons_and_stations(primary: RigidBody2D) -> void:
|
||||
var num_moons = randi_range(min_moons, max_moons)
|
||||
var moon_orbit_radius = 5e7
|
||||
var moon_orbit_radius = min_planetary_orbit_radius
|
||||
|
||||
for i in range(num_moons):
|
||||
var moon_instance = moon_scene.instantiate() as CelestialBody
|
||||
system_data.moons.append(moon_instance)
|
||||
moon_instance.name = "Moon " + str(i + 1)
|
||||
moon_instance.primary = primary
|
||||
moon_instance.sim_scale = sim_scale
|
||||
moon_instance.mass_real = randf_range(1e22, 1e23)
|
||||
moon_instance.orbit_radius_real = moon_orbit_radius + randf_range(1e7, 5e7)
|
||||
moon_instance.mass = MOON_MASS # randf_range(1e22, 1e23)
|
||||
moon_instance.orbit_radius_real = moon_orbit_radius + randf_range(0, 50)
|
||||
_create_body_in_ring(primary, moon_instance)
|
||||
moon_orbit_radius = moon_instance.orbit_radius_real
|
||||
|
||||
# Generate a space station.
|
||||
var station_instance = station_scene.instantiate() as CelestialBody
|
||||
system_data.stations.append(station_instance)
|
||||
station_instance.name = "Station"
|
||||
station_instance.primary = primary
|
||||
station_instance.sim_scale = sim_scale
|
||||
station_instance.mass_real = 1e8
|
||||
station_instance.orbit_radius_real = moon_orbit_radius + 5e7
|
||||
station_instance.mass = STATION_MASS
|
||||
station_instance.orbit_radius_real = moon_orbit_radius + randf_range(0, 50)
|
||||
_create_body_in_ring(primary, station_instance)
|
||||
|
||||
# Creates a single asteroid belt.
|
||||
@ -178,11 +188,11 @@ func _create_asteroid_belt(primary: RigidBody2D, initial_offset: float) -> Aster
|
||||
asteroid_instance.name = "Asteroid " + str(i + 1)
|
||||
asteroid_instance.primary = primary
|
||||
asteroid_instance.sim_scale = sim_scale
|
||||
asteroid_instance.mass_real = randf_range(1e10, 1e23)
|
||||
asteroid_instance.mass = ASTEROID_MASS # randf_range(1e10, 1e23)
|
||||
|
||||
belt.asteroids.append(asteroid_instance)
|
||||
|
||||
belt.mass = belt.asteroids.reduce(func(accum, asteroid : CelestialBody): return accum + asteroid.mass_real, 0.0)
|
||||
belt.mass = belt.asteroids.reduce(func(accum, asteroid : CelestialBody): return accum + asteroid.mass, 0.0)
|
||||
var offset = belt.mass * orbit_buffer
|
||||
belt.centered_radius = initial_offset + offset
|
||||
|
||||
@ -196,21 +206,19 @@ func _create_asteroid_belt(primary: RigidBody2D, initial_offset: float) -> Aster
|
||||
|
||||
# Helper function to instantiate and place a body in a ring.
|
||||
func _create_body_in_ring(primary: CelestialBody, body_instance: CelestialBody) -> void:
|
||||
var stable_velocity = calculate_stable_orbit_velocity(body_instance.orbit_radius_real, primary.mass_real)
|
||||
#var stable_velocity = calculate_stable_orbit_velocity(body_instance.orbit_radius_real, primary.mass_real)
|
||||
|
||||
var initial_position_vector = Vector2(body_instance.orbit_radius_real, 0).rotated(randf() * TAU)
|
||||
body_instance.global_position_real = primary.global_position_real + initial_position_vector
|
||||
body_instance.global_position = body_instance.global_position_real / sim_scale
|
||||
|
||||
var body_velocity_vector = Vector2(0, stable_velocity).rotated(initial_position_vector.angle() + PI / 2)
|
||||
body_instance.linear_velocity_real = body_instance.calculate_initial_orbit_real(primary, body_instance)
|
||||
|
||||
body_instance.global_position = primary.global_position_real + initial_position_vector
|
||||
|
||||
primary.add_child(body_instance)
|
||||
print("Created " + body_instance.name + " with radius " + str(body_instance.orbit_radius_real) + " and mass " + str(body_instance.mass_real))
|
||||
body_instance.linear_velocity = body_instance.calculate_initial_orbit_real(primary, body_instance)
|
||||
print("Created " + body_instance.name + " with radius " + str(body_instance.orbit_radius_real) + " and mass " + str(body_instance.mass))
|
||||
print("Initial orbital velocity is: " + str(body_instance.linear_velocity))
|
||||
|
||||
# Calculates the velocity required for a stable circular orbit.
|
||||
func calculate_stable_orbit_velocity(orbit_radius: float, primary_mass: float) -> float:
|
||||
return sqrt(G * primary_mass / orbit_radius)
|
||||
#func calculate_stable_orbit_velocity(orbit_radius: float, primary_mass: float) -> float:
|
||||
#return sqrt(G * primary_mass / orbit_radius)
|
||||
|
||||
# Recursively finds all celestial bodies in the scene.
|
||||
func get_all_bodies() -> Array:
|
||||
@ -236,6 +244,7 @@ class AsteroidBelt:
|
||||
class SystemData:
|
||||
var star : CelestialBody
|
||||
var planets : Array[CelestialBody]
|
||||
var moons: Array[CelestialBody]
|
||||
var stations : Array[CelestialBody]
|
||||
var belts : Array[AsteroidBelt]
|
||||
|
||||
@ -243,6 +252,8 @@ class SystemData:
|
||||
var bodies : Array[CelestialBody] = [star]
|
||||
bodies.append_array(planets)
|
||||
bodies.append_array(stations)
|
||||
|
||||
bodies.append_array(moons)
|
||||
|
||||
var all_asteroids : Array[CelestialBody] = []
|
||||
for belt in belts:
|
||||
|
||||
@ -10,7 +10,7 @@ func get_class_name() -> String:
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
# A Station has negligible mass for physics calculations.
|
||||
mass = 0.001
|
||||
#mass = 0.001
|
||||
radius = 15.0
|
||||
|
||||
# You can set a default texture here.
|
||||
|
||||
Reference in New Issue
Block a user