Movement accelerations use two step euler method

This commit is contained in:
Jakob Feldmann 2022-05-29 23:29:00 +02:00
parent 6bf50d1bab
commit 8d92d285d9
4 changed files with 75 additions and 85 deletions

View File

@ -60,41 +60,30 @@ func calculate_grounded_velocity(
if velocity.x < 0: if velocity.x < 0:
velocity_direction = -1.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): if is_equal_approx(direction.x, 0):
var deceleration_force = calculate_deceleration_force( out_vel.x = PhysicsFunc.two_step_euler(
_gravity, mass, delta out_vel.x, deceleration_force * -1 * velocity_direction, mass, delta
) )
# Translates velocity back to force and subtracts deceleration force if abs(out_vel.x) > abs(velocity.x):
var result_force = (
abs(PhysicsFunc.convert_velocity_to_force(velocity.x, mass, delta))
- deceleration_force
)
if result_force <= 0:
out_vel.x = 0 out_vel.x = 0
else:
out_vel.x = (
PhysicsFunc.convert_force_to_velocity(result_force, mass, delta)
* velocity_direction
)
else: else:
# Reversing movement # Reversing movement
# When turning the opposite direction, friction is added to the opposite acceleration movement # When turning the opposite direction, friction is added to the opposite acceleration movement
var reverse_move = is_reversing_horizontal_movement(direction) var reverse_move = is_reversing_horizontal_movement(direction)
if reverse_move: if reverse_move:
out_vel.x -= ( out_vel.x = PhysicsFunc.two_step_euler(
PhysicsFunc.convert_force_to_velocity( out_vel.x,
calculate_deceleration_force(_gravity, mass, delta), deceleration_force * -1.66 * velocity_direction,
mass, mass,
delta delta
) )
* velocity_direction
)
# Normal movement # Normal movement
if abs(velocity.x) < max_velocity[state]: if abs(velocity.x) < max_velocity[state]:
out_vel.x += ( out_vel.x = PhysicsFunc.two_step_euler(
delta out_vel.x,
* (
( (
( (
acceleration_force[state].x acceleration_force[state].x
@ -103,10 +92,10 @@ func calculate_grounded_velocity(
* int(init_boost) * int(init_boost)
) )
) )
/ mass
)
* direction.x * direction.x
) ),
mass,
delta
) )
elif !reverse_move: elif !reverse_move:
out_vel.x = max_velocity[state] * direction.x out_vel.x = max_velocity[state] * direction.x
@ -123,6 +112,8 @@ func calculate_grounded_velocity(
return out_vel 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: func is_reversing_horizontal_movement(direction: Vector2) -> bool:
return ( return (
(direction.x > 0 && velocity.x < 0) (direction.x > 0 && velocity.x < 0)
@ -166,11 +157,9 @@ func is_correct_airstrafe_input() -> bool:
) )
# TODO Comments for parameters # Calculates the force of the ground friction
func calculate_deceleration_force( func calculate_deceleration_force(_gravity: float, mass: float) -> float:
_gravity: float, mass: float, delta: float return normal_floor_friction * _gravity * mass
) -> float:
return normal_floor_friction * _gravity * mass * delta
func calculate_jump_velocity( func calculate_jump_velocity(
@ -188,10 +177,11 @@ func calculate_jump_velocity(
* abs(velocity.x) * abs(velocity.x)
* mass * mass
) )
linear_velocity.y = ( linear_velocity.y = PhysicsFunc.two_step_euler(
((acceleration_force[state].y + additive_jump_force) / mass) 0,
* delta (acceleration_force[state].y + additive_jump_force) * -1,
* -1 mass,
delta
) )
if !Input.is_action_pressed("jump"): if !Input.is_action_pressed("jump"):
@ -213,10 +203,11 @@ func calculate_jump_velocity(
linear_velocity.x += inair_velocity * direction.x linear_velocity.x += inair_velocity * direction.x
if is_correct_airstrafe_input() && !walljumping: if is_correct_airstrafe_input() && !walljumping:
linear_velocity.x += ( linear_velocity.x = PhysicsFunc.two_step_euler(
direction.x linear_velocity.x,
* acceleration_force["air_strafe"].x acceleration_force["air_strafe"].x * direction.x,
* delta mass,
delta
) )
air_strafe_charges -= 1 air_strafe_charges -= 1
@ -230,10 +221,9 @@ func calculate_fall_velocity(
) -> Vector2: ) -> Vector2:
if velocity.y < max_velocity["fall"]: if velocity.y < max_velocity["fall"]:
# linear_velocity.y += _gravity * delta # linear_velocity.y += _gravity * delta
# Better explicit euler step linear_velocity.y = PhysicsFunc.two_step_euler(
var step1vel = linear_velocity.y + _gravity * 0.5 * delta linear_velocity.y, _gravity * mass, mass, delta
var step2vel = step1vel + _gravity * 0.5 * delta )
linear_velocity.y = step2vel
else: else:
linear_velocity.y = max_velocity["fall"] linear_velocity.y = max_velocity["fall"]
if is_equal_approx(velocity.x, 0): if is_equal_approx(velocity.x, 0):
@ -242,10 +232,11 @@ func calculate_fall_velocity(
if Input.is_action_just_pressed("jump"): if Input.is_action_just_pressed("jump"):
jump_buffer_filled = true jump_buffer_filled = true
if is_correct_airstrafe_input(): if is_correct_airstrafe_input():
linear_velocity.x += ( linear_velocity.x = PhysicsFunc.two_step_euler(
direction.x linear_velocity.x,
* acceleration_force["air_strafe"].x acceleration_force["air_strafe"].x * direction.x,
* delta mass,
delta
) )
air_strafe_charges -= 1 air_strafe_charges -= 1
return linear_velocity return linear_velocity
@ -256,34 +247,22 @@ func calculate_wallslide_velocity(
) -> Vector2: ) -> Vector2:
# Walljump mechanics # Walljump mechanics
if is_correct_walljump_input(direction): if is_correct_walljump_input(direction):
print("should walljump") linear_velocity.y = PhysicsFunc.two_step_euler(
# TODO This +0.01 indicates a larger problem with division through possible 0 values!! linear_velocity.y,
var multiplicator = max( acceleration_force["walljump"].y * -1,
min( mass,
1, delta
(
acceleration_force["walljump"].y
/ (((velocity.y / delta) / mass) + 0.01)
) )
), linear_velocity.x += PhysicsFunc.two_step_euler(
0.7 linear_velocity.x,
acceleration_force["walljump"].x * direction.x,
mass,
delta
) )
print_debug(multiplicator)
linear_velocity.y += (
(acceleration_force["walljump"].y / mass)
* -1
* delta
* multiplicator
)
linear_velocity.x += (
acceleration_force["walljump"].x
* delta
* direction.x
)
print_debug(linear_velocity)
else: else:
linear_velocity.y += _gravity * delta * 0.4 linear_velocity.y = PhysicsFunc.two_step_euler(
# linear_velocity.x += inair_velocity * direction.x linear_velocity.y, _gravity * mass * 0.5, mass, delta
)
return linear_velocity return linear_velocity

View File

@ -7,7 +7,8 @@ const FLOOR_NORMAL := Vector2.UP
var stomp_feedback := 1000.0 var stomp_feedback := 1000.0
var inair_velocity := 21 var inair_velocity := 21
var wallslide_threshold := 300 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 := { var max_velocity := {
"walk": 120, "run": 160, "fall": 400, "walljump": 150, "idle": 120 "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 # Oriented around deltas of 0.0166666...s
# newtonmeters is the unit # newtonmeters is the unit
var acceleration_force := { var acceleration_force := {
"walk": Vector2(2000, 108000), "walk": Vector2(2000, 68000),
"idle": Vector2(2000, 108000), "idle": Vector2(2000, 68000),
"run": Vector2(2000, 108000), "run": Vector2(2000, 68000),
"walljump": Vector2(7800, 108000), "walljump": Vector2(30000, 58000),
"air_strafe": Vector2(4800, 0) "air_strafe": Vector2(20000, 0)
} }
# Gravity as m/s^2
var _gravity: float = PhysicsConst.gravity var _gravity: float = PhysicsConst.gravity
# Mass of Blobby
# Kilograms # Kilograms
var mass := 6.5 var mass := 6.5

View File

@ -1 +1 @@
const gravity: float = 1111.0 const gravity: float = 700.0

View File

@ -10,3 +10,11 @@ static func complete_unelastic_shock(
v1: float, v2: float, m1: float, m2: float v1: float, v2: float, m1: float, m2: float
) -> float: ) -> float:
return (m1 * v1 + m2 * v2) / (m1 + m2) 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