Created
April 5, 2024 12:22
-
-
Save N-Carter/132f79baca4a4229a12ed884356ff158 to your computer and use it in GitHub Desktop.
Revisions
-
N-Carter created this gist
Apr 5, 2024 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,160 @@ # 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