95 lines
3.3 KiB
GDScript3
95 lines
3.3 KiB
GDScript3
|
|
class_name CelestialBody
|
||
|
|
extends RigidBody2D
|
||
|
|
|
||
|
|
# The celestial body that this body orbits.
|
||
|
|
@export var primary: CelestialBody
|
||
|
|
|
||
|
|
# Real-world gravitational constant.
|
||
|
|
const G_REAL = 6.674e-11
|
||
|
|
|
||
|
|
# This is a placeholder for your pixel art texture.
|
||
|
|
@export var texture: Texture2D
|
||
|
|
|
||
|
|
# 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
|
||
|
|
|
||
|
|
# Default color based on body type for visualization.
|
||
|
|
var body_color: Color = Color.ORANGE_RED
|
||
|
|
|
||
|
|
func get_class_name() -> String:
|
||
|
|
return "CelestialBody"
|
||
|
|
|
||
|
|
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 * 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
|
||
|
|
|
||
|
|
# Set the color based on the class name for easy differentiation.
|
||
|
|
|
||
|
|
match get_class_name():
|
||
|
|
"Star":
|
||
|
|
body_color = Color.GOLD
|
||
|
|
"Planet":
|
||
|
|
body_color = Color.BLUE
|
||
|
|
"Moon":
|
||
|
|
body_color = Color.PURPLE
|
||
|
|
"Station":
|
||
|
|
body_color = Color.WHITE
|
||
|
|
"Asteroid":
|
||
|
|
body_color = Color.BROWN
|
||
|
|
_:
|
||
|
|
body_color = Color.ORANGE_RED
|
||
|
|
|
||
|
|
|
||
|
|
# 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 - state.transform.origin
|
||
|
|
var distance_squared = direction_to_primary.length_squared()
|
||
|
|
|
||
|
|
# 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 * primary.mass) / distance_squared
|
||
|
|
|
||
|
|
# Apply the force in the direction of the primary.
|
||
|
|
state.apply_central_force(direction_to_primary.normalized() * force_magnitude)
|
||
|
|
|
||
|
|
# We force a redraw here to update the body's visual representation.
|
||
|
|
queue_redraw()
|
||
|
|
|
||
|
|
# Override the default drawing function to draw the body.
|
||
|
|
# This is useful for debugging and visualization.
|
||
|
|
func _draw() -> void:
|
||
|
|
if texture:
|
||
|
|
# If a texture is assigned, draw it.
|
||
|
|
var size = Vector2(radius * 2, radius * 2)
|
||
|
|
var offset = -size / 2.0
|
||
|
|
draw_texture_rect(texture, Rect2(offset, size), false)
|
||
|
|
else:
|
||
|
|
# Otherwise, draw a simple placeholder circle.
|
||
|
|
draw_circle(Vector2.ZERO, radius, body_color)
|
||
|
|
|
||
|
|
|
||
|
|
# Calculates the velocity required for a stable circular orbit.
|
||
|
|
func get_stable_orbit_velocity(primary_mass_real: float, distance_real: float) -> float:
|
||
|
|
# The formula for real-world orbital velocity is v = sqrt(G * M / r)
|
||
|
|
var real_world_velocity = sqrt((G_REAL * primary_mass_real) / distance_real)
|
||
|
|
# Scale this velocity down to the simulation scale before returning.
|
||
|
|
return real_world_velocity / sim_scale
|