Skip to content

Instantly share code, notes, and snippets.

@N-Carter
Created April 5, 2024 12:22
Show Gist options
  • Save N-Carter/132f79baca4a4229a12ed884356ff158 to your computer and use it in GitHub Desktop.
Save N-Carter/132f79baca4a4229a12ed884356ff158 to your computer and use it in GitHub Desktop.
# Godot 3.5.2
class_name Gravity
extends Node
export var gravity_constant := 10000.0
var _moving_masses : Array
var _static_masses : Array
class OrbitalBody:
var body : Planetoid
var moons := [] # Array of OrbitalBody objects, not Planetoids!
func _to_string() -> String:
var string := "(Body \"%s\", [" % body.name
for moon in moons:
string += moon.to_string()
string += "])"
return string
var _orbital_bodies := [] # Bodies in this array just orbit the origin.
func _init():
Game.gravity = self
func _ready() -> void:
# Grab all the bodies in the system and organise them into a hierarchy:
var connections := {} # {Planetoid : OrbitalBody}
_static_masses = get_tree().get_nodes_in_group("static_mass")
for static_mass in _static_masses:
var body := static_mass as Planetoid
if is_instance_valid(body):
var orbital_body := OrbitalBody.new()
orbital_body.body = body
connections[body] = orbital_body
for static_mass in _static_masses:
var body := static_mass as Planetoid
if is_instance_valid(body):
var parent_body := body.get_parent_body()
if is_instance_valid(parent_body):
connections[parent_body].moons.append(connections[body])
else:
# If it has no parent, it just orbits the origin:
_orbital_bodies.append(connections[body])
for body in _orbital_bodies:
print(body.to_string())
func _physics_process(_delta):
# Only handling forces applied to moving masses by static masses right now:
_moving_masses = get_tree().get_nodes_in_group("moving_mass")
_static_masses = get_tree().get_nodes_in_group("static_mass")
for mass in _moving_masses:
var body := mass as RigidBody2D
for static_mass in _static_masses:
var static_body := static_mass as RigidBody2D
var force := _calculate_gravity(body, static_body)
# print("%0.3f, %s" % [force.length(), force])
body.add_central_force(force)
func _calculate_gravity(body_a : RigidBody2D, body_b : RigidBody2D) -> Vector2:
# F = (G * m1 * m2) / d^2
var direction := body_b.global_position - body_a.global_position
var force := (gravity_constant * body_a.mass * body_b.mass) / direction.length_squared()
return direction.normalized() * force
func _gravity_for_trajectory(position_a : Vector2, mass_a : float, body_b : RigidBody2D) -> Vector2:
# F = (G * m1 * m2) / d^2
var direction := body_b.global_position - position_a
mass_a = 1.0 # FIXME: Have to set mass_a to 1.0 for some reason?
var force := (gravity_constant * mass_a * body_b.mass) / direction.length_squared()
return direction.normalized() * force
func calculate_trajectory(body : RigidBody2D, duration : float, delta : float) -> Array:
var points := []
var position := body.global_position
var velocity := body.linear_velocity
points.append(position)
var time := 0.0
while time < duration:
for static_mass in _static_masses:
var static_body := static_mass as RigidBody2D
var force := _gravity_for_trajectory(position, body.mass, static_body)
velocity += force * delta
# Stop if the trajectory passes through a planetoid:
if (static_mass.global_position - position).length() < static_mass.get_radius():
if points.size() > 2:
points.pop_back()
return points
position += velocity * delta
points.append(position)
time += delta
return points
func calculate_trajectory_line(body : RigidBody2D, duration : float, delta : float, line : Line2D) -> void:
line.clear_points()
var position := body.global_position
var velocity := body.linear_velocity
var time := 0.0
line.add_point(Vector2.ZERO)
while time < duration:
for static_mass in _static_masses:
var static_body := static_mass as RigidBody2D
var force := _gravity_for_trajectory(position, body.mass, static_body)
velocity += force * delta
# Stop if the trajectory passes through a planetoid:
if (static_mass.global_position - position).length() < static_mass.get_radius():
var count := line.get_point_count()
if count > 2:
line.remove_point(count - 1)
return
position += velocity * delta
line.add_point(line.to_local(position))
time += delta
func get_closest_static_mass(global_point : Vector2, masses : Array = []) -> RigidBody2D:
if masses == []:
masses = get_tree().get_nodes_in_group("static_mass")
var shortest_distance_sq := INF
var closest_mass : RigidBody2D
for m in masses:
var mass := m as RigidBody2D
var distance_sq := (mass.global_position - global_point).length_squared()
if distance_sq < shortest_distance_sq:
shortest_distance_sq = distance_sq
closest_mass = mass
return closest_mass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment