Last active
June 30, 2024 02:43
-
-
Save RepComm/e807effe728121d811438631b625266b to your computer and use it in GitHub Desktop.
2d spring implementation for godot v4 gdscript, simply assign a and b RigidBody2D, script doesn't have to be attached to rigidbodys, just needs to be in the scene
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 characters
extends Node2D | |
@export | |
var a: RigidBody2D = null | |
@export | |
var b: RigidBody2D = null | |
@export | |
var a_affected: bool = false | |
@export | |
var b_affected: bool = false | |
@export | |
var stiffness = 10 | |
@export | |
var rest_length = 10 | |
@export | |
var damping = 0.5 | |
#a.position - b.position | |
var v_pos_diff = Vector2() | |
#calculated length currently at | |
var v_actual_length: float = 1 | |
#normalized direction from a to b | |
var v_a_dir = Vector2() | |
#v_a_dir as euler | |
var v_a_angle = Vector2() | |
var v_b_dir = Vector2() | |
var v_b_angle = Vector2() | |
#diff of body velocities | |
var v_vel_diff = 0 | |
#dot product of a-b velocity and a->b direction | |
var v_vel_diff_dot = 0 | |
#current damping applied in step | |
var v_damp_force = 0 | |
#spring to resting length force | |
var v_spring_force = 0 | |
var v_total_force = 0 | |
var v_a_force = Vector2() | |
var v_b_force = Vector2() | |
# Called when the node enters the scene tree for the first time. | |
func _ready(): | |
pass # Replace with function body. | |
# Called every frame. 'delta' is the elapsed time since the previous frame. | |
func _physics_process(delta): | |
if a == null or b == null: | |
return | |
#doesn't create a new vec, just fyi | |
v_pos_diff = b.position - a.position | |
v_actual_length = v_pos_diff.length() | |
v_a_dir = v_pos_diff.normalized() | |
v_a_angle = v_a_dir.angle() | |
v_b_dir = -v_a_dir | |
v_b_angle = v_b_dir.angle() | |
v_vel_diff = b.linear_velocity - a.linear_velocity | |
v_vel_diff_dot = v_vel_diff.dot(v_a_dir) | |
#calculate damp force | |
v_damp_force = v_vel_diff_dot * damping | |
#Hooke's law spring force | |
v_spring_force = (v_actual_length - rest_length) * stiffness | |
v_total_force = v_spring_force + v_damp_force | |
v_a_force = (v_a_dir * v_total_force) / a.mass | |
v_b_force = (v_b_dir * v_total_force) / b.mass | |
if not a_affected and not a.freeze: | |
a.apply_central_force(v_a_force) | |
if not b_affected and not b.freeze: | |
b.apply_central_force(v_b_force) | |
self.position = a.position.lerp(b.position, 0.5) | |
self.rotation = v_a_angle | |
self.scale.x = v_actual_length / rest_length | |
pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Revision 2: extends Node2D, scales self x based on a and b rigid bodies, positions self between a and b rigid bodies, rotates to align between a and b rigid bodies. You can attach a visual object as a child to the spring to represent the spring on screen and have full control of what is rendered.