extends Node2D const PhysicsFunc = preload("res://src/Utilities/Physic/PhysicsFunc.gd") const PhysicsConst = preload("res://src/Utilities/Physic/PhysicsConst.gd") var mass = 1 var coupled_mass = mass var spring_k = -600 var start_y = 0 var y_velocity = 0 var friction = 0.91 # TODO Only store velocity coming to the springs orientation var stored_incoming_velocity = 0 var coupled_body = null var shock_ready = true func _ready() -> void: start_y = self.position.y # TODO Limit spring deformation # Called every frame. 'delta' is the elapsed time since the previous frame. func _physics_process(delta: float) -> void: var bc = _body_contact() if !bc: shock_ready = true if bc && shock_ready: _Kinematic_Body_on_Spring() var spring_force = spring_k * (self.position.y - self.start_y) if coupled_body != null: coupled_mass = mass + coupled_body.mass else: coupled_mass = mass var weight_force = coupled_mass * PhysicsConst.gravity var result_force = weight_force + spring_force y_velocity = PhysicsFunc.two_step_euler( y_velocity, result_force, coupled_mass, delta ) y_velocity *= friction self.position.y += y_velocity * delta func _body_contact() -> bool: var areas: Array = $SpringSkin.get_overlapping_areas() for i in range(0, areas.size()): if areas[i].name == "BlobbySkin": coupled_body = areas[i].get_parent() return true coupled_body = null return false func _Kinematic_Body_on_Spring() -> void: var a_velocity = stored_incoming_velocity var a_mass = coupled_body.mass var b_velocity = y_velocity var b_mass = mass y_velocity += PhysicsFunc.complete_unelastic_shock( a_velocity, b_velocity, a_mass, b_mass ) print(y_velocity) stored_incoming_velocity = 0 shock_ready = false func _on_SpringSkin_area_exited(_area: Area2D) -> void: var displacement = self.position.y - self.start_y var potential_spring_energy = spring_k * 0.5 * pow(displacement, 2) var mass_ratio = 1 - mass / coupled_mass var transferred_kinetic_energy = potential_spring_energy * mass_ratio var kinetic_energy_in_velocity = ( -sign(displacement) * sqrt( abs( 2 * transferred_kinetic_energy / max(coupled_mass - mass, 0.001) ) ) ) if coupled_body != null: coupled_body.velocity.y += kinetic_energy_in_velocity func _on_EnteringVelocityDetector_area_entered(area: Area2D) -> void: if area.name == "BlobbySkin": if area.get_parent().velocity.y > 0: stored_incoming_velocity = area.get_parent().velocity.y