Created
April 5, 2024 12:22
-
-
Save N-Carter/132f79baca4a4229a12ed884356ff158 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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