diff --git a/src/Actors/Blobby/Blobby.gd b/src/Actors/Blobby/Blobby.gd index c7ec9bd..e5a9737 100644 --- a/src/Actors/Blobby/Blobby.gd +++ b/src/Actors/Blobby/Blobby.gd @@ -60,53 +60,42 @@ func calculate_grounded_velocity( if velocity.x < 0: velocity_direction = -1.0 - # Stopping movement + var deceleration_force = calculate_deceleration_force(_gravity, mass) + + # Slowing down movement when not controlling direction if is_equal_approx(direction.x, 0): - var deceleration_force = calculate_deceleration_force( - _gravity, mass, delta + out_vel.x = PhysicsFunc.two_step_euler( + out_vel.x, deceleration_force * -1 * velocity_direction, mass, delta ) - # Translates velocity back to force and subtracts deceleration force - var result_force = ( - abs(PhysicsFunc.convert_velocity_to_force(velocity.x, mass, delta)) - - deceleration_force - ) - if result_force <= 0: + if abs(out_vel.x) > abs(velocity.x): out_vel.x = 0 - else: - out_vel.x = ( - PhysicsFunc.convert_force_to_velocity(result_force, mass, delta) - * velocity_direction - ) else: # Reversing movement # When turning the opposite direction, friction is added to the opposite acceleration movement var reverse_move = is_reversing_horizontal_movement(direction) if reverse_move: - out_vel.x -= ( - PhysicsFunc.convert_force_to_velocity( - calculate_deceleration_force(_gravity, mass, delta), - mass, - delta - ) - * velocity_direction + out_vel.x = PhysicsFunc.two_step_euler( + out_vel.x, + deceleration_force * -1.66 * velocity_direction, + mass, + delta ) # Normal movement if abs(velocity.x) < max_velocity[state]: - out_vel.x += ( - delta - * ( + out_vel.x = PhysicsFunc.two_step_euler( + out_vel.x, + ( ( - ( - acceleration_force[state].x - + ( - init_acceleration_force[init_boost_type] - * int(init_boost) - ) + acceleration_force[state].x + + ( + init_acceleration_force[init_boost_type] + * int(init_boost) ) - / mass ) * direction.x - ) + ), + mass, + delta ) elif !reverse_move: out_vel.x = max_velocity[state] * direction.x @@ -123,6 +112,8 @@ func calculate_grounded_velocity( return out_vel +# Determines if the player has reversed the steering direction +# in reference to the current movement direction func is_reversing_horizontal_movement(direction: Vector2) -> bool: return ( (direction.x > 0 && velocity.x < 0) @@ -166,11 +157,9 @@ func is_correct_airstrafe_input() -> bool: ) -# TODO Comments for parameters -func calculate_deceleration_force( - _gravity: float, mass: float, delta: float -) -> float: - return normal_floor_friction * _gravity * mass * delta +# Calculates the force of the ground friction +func calculate_deceleration_force(_gravity: float, mass: float) -> float: + return normal_floor_friction * _gravity * mass func calculate_jump_velocity( @@ -188,10 +177,11 @@ func calculate_jump_velocity( * abs(velocity.x) * mass ) - linear_velocity.y = ( - ((acceleration_force[state].y + additive_jump_force) / mass) - * delta - * -1 + linear_velocity.y = PhysicsFunc.two_step_euler( + 0, + (acceleration_force[state].y + additive_jump_force) * -1, + mass, + delta ) if !Input.is_action_pressed("jump"): @@ -213,10 +203,11 @@ func calculate_jump_velocity( linear_velocity.x += inair_velocity * direction.x if is_correct_airstrafe_input() && !walljumping: - linear_velocity.x += ( - direction.x - * acceleration_force["air_strafe"].x - * delta + linear_velocity.x = PhysicsFunc.two_step_euler( + linear_velocity.x, + acceleration_force["air_strafe"].x * direction.x, + mass, + delta ) air_strafe_charges -= 1 @@ -230,10 +221,9 @@ func calculate_fall_velocity( ) -> Vector2: if velocity.y < max_velocity["fall"]: # linear_velocity.y += _gravity * delta - # Better explicit euler step - var step1vel = linear_velocity.y + _gravity * 0.5 * delta - var step2vel = step1vel + _gravity * 0.5 * delta - linear_velocity.y = step2vel + linear_velocity.y = PhysicsFunc.two_step_euler( + linear_velocity.y, _gravity * mass, mass, delta + ) else: linear_velocity.y = max_velocity["fall"] if is_equal_approx(velocity.x, 0): @@ -242,10 +232,11 @@ func calculate_fall_velocity( if Input.is_action_just_pressed("jump"): jump_buffer_filled = true if is_correct_airstrafe_input(): - linear_velocity.x += ( - direction.x - * acceleration_force["air_strafe"].x - * delta + linear_velocity.x = PhysicsFunc.two_step_euler( + linear_velocity.x, + acceleration_force["air_strafe"].x * direction.x, + mass, + delta ) air_strafe_charges -= 1 return linear_velocity @@ -256,34 +247,22 @@ func calculate_wallslide_velocity( ) -> Vector2: # Walljump mechanics if is_correct_walljump_input(direction): - print("should walljump") - # TODO This +0.01 indicates a larger problem with division through possible 0 values!! - var multiplicator = max( - min( - 1, - ( - acceleration_force["walljump"].y - / (((velocity.y / delta) / mass) + 0.01) - ) - ), - 0.7 + linear_velocity.y = PhysicsFunc.two_step_euler( + linear_velocity.y, + acceleration_force["walljump"].y * -1, + mass, + delta ) - print_debug(multiplicator) - linear_velocity.y += ( - (acceleration_force["walljump"].y / mass) - * -1 - * delta - * multiplicator + linear_velocity.x += PhysicsFunc.two_step_euler( + linear_velocity.x, + acceleration_force["walljump"].x * direction.x, + mass, + delta ) - linear_velocity.x += ( - acceleration_force["walljump"].x - * delta - * direction.x - ) - print_debug(linear_velocity) else: - linear_velocity.y += _gravity * delta * 0.4 - # linear_velocity.x += inair_velocity * direction.x + linear_velocity.y = PhysicsFunc.two_step_euler( + linear_velocity.y, _gravity * mass * 0.5, mass, delta + ) return linear_velocity diff --git a/src/Actors/Player.gd b/src/Actors/Player.gd index 8be3534..3f8f9b3 100644 --- a/src/Actors/Player.gd +++ b/src/Actors/Player.gd @@ -7,7 +7,8 @@ const FLOOR_NORMAL := Vector2.UP var stomp_feedback := 1000.0 var inair_velocity := 21 var wallslide_threshold := 300 -var normal_floor_friction := 28 +# TODO Map to floor types and move to physics constants +var normal_floor_friction := 0.5 var max_velocity := { "walk": 120, "run": 160, "fall": 400, "walljump": 150, "idle": 120 } @@ -19,13 +20,15 @@ var init_acceleration_force := { # Oriented around deltas of 0.0166666...s # newtonmeters is the unit var acceleration_force := { - "walk": Vector2(2000, 108000), - "idle": Vector2(2000, 108000), - "run": Vector2(2000, 108000), - "walljump": Vector2(7800, 108000), - "air_strafe": Vector2(4800, 0) + "walk": Vector2(2000, 68000), + "idle": Vector2(2000, 68000), + "run": Vector2(2000, 68000), + "walljump": Vector2(30000, 58000), + "air_strafe": Vector2(20000, 0) } +# Gravity as m/s^2 var _gravity: float = PhysicsConst.gravity +# Mass of Blobby # Kilograms var mass := 6.5 diff --git a/src/Utilities/Physic/PhysicsConst.gd b/src/Utilities/Physic/PhysicsConst.gd index d97687a..77504e1 100644 --- a/src/Utilities/Physic/PhysicsConst.gd +++ b/src/Utilities/Physic/PhysicsConst.gd @@ -1 +1 @@ -const gravity: float = 1111.0 +const gravity: float = 700.0 diff --git a/src/Utilities/Physic/PhysicsFunc.gd b/src/Utilities/Physic/PhysicsFunc.gd index c7ff0a5..d659994 100644 --- a/src/Utilities/Physic/PhysicsFunc.gd +++ b/src/Utilities/Physic/PhysicsFunc.gd @@ -10,3 +10,11 @@ static func complete_unelastic_shock( v1: float, v2: float, m1: float, m2: float ) -> float: return (m1 * v1 + m2 * v2) / (m1 + m2) + + +# Explicit euler method looking one step into the future +# Returns the mean velocity of applying the force two times +static func two_step_euler(v0, force, mass, delta) -> float: + var v1 = v0 + force / mass * delta + var v2 = v1 + force / mass * delta + return (v1 + v2) / 2