Movement accelerations use two step euler method
This commit is contained in:
parent
6bf50d1bab
commit
8d92d285d9
@ -60,53 +60,42 @@ 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
|
+ (
|
||||||
+ (
|
init_acceleration_force[init_boost_type]
|
||||||
init_acceleration_force[init_boost_type]
|
* 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)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
0.7
|
|
||||||
)
|
)
|
||||||
print_debug(multiplicator)
|
linear_velocity.x += PhysicsFunc.two_step_euler(
|
||||||
linear_velocity.y += (
|
linear_velocity.x,
|
||||||
(acceleration_force["walljump"].y / mass)
|
acceleration_force["walljump"].x * direction.x,
|
||||||
* -1
|
mass,
|
||||||
* delta
|
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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
const gravity: float = 1111.0
|
const gravity: float = 700.0
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user