237 lines
6.6 KiB
GDScript
237 lines
6.6 KiB
GDScript
extends Player
|
|
|
|
export var init_boost := false
|
|
onready var wall_touch_direction = 0
|
|
onready var left_wall_raycasts = $WallRaycasts/LeftWallRaycast
|
|
onready var right_wall_raycasts = $WallRaycasts/RightWallRaycast
|
|
|
|
|
|
func _on_EnemyDetector_area_entered(area: Area2D) -> void:
|
|
_velocity = calculate_stomp_velocity(_velocity, stomp_feedback)
|
|
|
|
|
|
func _on_EnemyDetector_body_entered(body: Node) -> void:
|
|
die()
|
|
|
|
|
|
func handle_grounded_movement(delta: float, direction: Vector2) -> Vector2:
|
|
return calculate_grounded_velocity(_velocity, delta, direction)
|
|
|
|
|
|
func handle_jump_movement(delta: float, direction: Vector2) -> Vector2:
|
|
return calculate_jump_velocity(_velocity, delta, direction)
|
|
|
|
|
|
func handle_fall_movement(delta: float, direction: Vector2) -> Vector2:
|
|
return calculate_fall_velocity(_velocity, delta, direction)
|
|
|
|
|
|
func handle_wallslide_movement(delta: float, direction: Vector2) -> Vector2:
|
|
return calculate_wallslide_velocity(_velocity, delta, direction)
|
|
|
|
|
|
func calculate_grounded_velocity(
|
|
linear_velocity: Vector2, delta: float, direction: Vector2
|
|
) -> Vector2:
|
|
var state = self.get_node("PlayerStateMachine").state
|
|
var out_vel := linear_velocity
|
|
var velocity_direction = 1.0
|
|
if _velocity.x < 0:
|
|
velocity_direction = -1.0
|
|
|
|
# Stopping movement
|
|
if direction.x == 0.0:
|
|
var deceleration_force = calculate_deceleration_force(
|
|
_gravity, mass, delta
|
|
)
|
|
# Translates velocity back to force and subtracts deceleration force
|
|
var result_force = (
|
|
abs(convert_velocity_to_force(_velocity.x, mass, delta))
|
|
- deceleration_force
|
|
)
|
|
if result_force <= 0:
|
|
out_vel.x = 0
|
|
else:
|
|
out_vel.x = (
|
|
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 -= (
|
|
convert_force_to_velocity(
|
|
calculate_deceleration_force(_gravity, mass, delta),
|
|
mass,
|
|
delta
|
|
)
|
|
* velocity_direction
|
|
)
|
|
# Normal movement
|
|
if abs(_velocity.x) < max_velocity[state]:
|
|
out_vel.x += (
|
|
delta
|
|
* (
|
|
(
|
|
(
|
|
acceleration_force[state].x
|
|
+ init_acceleration_force[state] * int(init_boost)
|
|
)
|
|
/ mass
|
|
)
|
|
* direction.x
|
|
)
|
|
)
|
|
elif ! reverse_move:
|
|
out_vel.x = max_velocity[state] * direction.x
|
|
# Jumping when grounded
|
|
if Input.is_action_just_pressed("jump"):
|
|
return calculate_jump_velocity(_velocity, delta, direction)
|
|
|
|
else:
|
|
out_vel.y = _gravity * delta
|
|
return out_vel
|
|
|
|
|
|
func is_reversing_horizontal_movement(direction: Vector2) -> bool:
|
|
return (
|
|
(direction.x > 0 && _velocity.x < 0)
|
|
|| (direction.x < 0 && _velocity.x >= 0)
|
|
)
|
|
|
|
|
|
# Returns if the character is touching a wall with its whole body
|
|
# Being able to touch a vertical surface over this length also makes it a qualified "wall"
|
|
# Also sets wall_touch_direction
|
|
# TODO Ugly side effect
|
|
# TODO Walljumping is a bit to radical behaving
|
|
func is_touching_wall_completely() -> bool:
|
|
for left_raycast in left_wall_raycasts.get_children():
|
|
wall_touch_direction = -1
|
|
if ! left_raycast.is_colliding():
|
|
for right_raycast in right_wall_raycasts.get_children():
|
|
wall_touch_direction = 1
|
|
if ! right_raycast.is_colliding():
|
|
wall_touch_direction = 0
|
|
return false
|
|
return true
|
|
|
|
|
|
func is_correct_walljump_input(direction: Vector2) -> bool:
|
|
return (
|
|
Input.is_action_just_pressed("jump")
|
|
&& abs(direction.x + wall_touch_direction) < 1
|
|
&& abs(direction.x + wall_touch_direction) >= 0
|
|
)
|
|
|
|
|
|
func convert_velocity_to_force(velocity, mass, delta) -> float:
|
|
return (velocity * mass) / delta
|
|
|
|
|
|
func convert_force_to_velocity(force, mass, delta) -> float:
|
|
return (force / mass) * delta
|
|
|
|
|
|
# TODO Save this static number somewhere else
|
|
func get_ground_friction() -> float:
|
|
return 22.0
|
|
|
|
|
|
# TODO Comments for parameters
|
|
func calculate_deceleration_force(_gravity: float, mass: float, delta: float) -> float:
|
|
return get_ground_friction() * _gravity * mass * delta
|
|
|
|
|
|
func calculate_jump_velocity(
|
|
linear_velocity: Vector2, delta: float, direction: Vector2
|
|
) -> Vector2:
|
|
var state = self.get_node("PlayerStateMachine").state
|
|
|
|
if Input.is_action_just_pressed("jump") && state != "jump":
|
|
var additive_jump_force = (
|
|
velocity_jump_boost_ratio
|
|
* abs(_velocity.x)
|
|
* mass
|
|
)
|
|
linear_velocity.y = (
|
|
((acceleration_force[state].y + additive_jump_force) / mass)
|
|
* -1
|
|
)
|
|
if (
|
|
is_touching_wall_completely()
|
|
&& is_correct_walljump_input(direction)
|
|
):
|
|
# The faster you are moving up the farther the walljump goes
|
|
linear_velocity.y = (acceleration_force["walljump"].y / mass) * -1
|
|
linear_velocity.x += max_velocity["walljump"] * direction.x
|
|
if ! Input.is_action_pressed("jump"):
|
|
# TODO This is so good not gonna lie
|
|
if _velocity.y > _gravity * delta * 10:
|
|
linear_velocity.y += _gravity * delta * 10
|
|
else:
|
|
linear_velocity.y += (
|
|
max(abs(linear_velocity.y), _gravity * delta)
|
|
/ 2
|
|
)
|
|
else:
|
|
linear_velocity.y += _gravity * delta * 0.88
|
|
if _velocity.x == 0:
|
|
linear_velocity.x += inair_velocity * direction.x
|
|
return linear_velocity
|
|
|
|
|
|
# Only applicable to downwards gravity
|
|
func calculate_fall_velocity(
|
|
linear_velocity: Vector2, delta: float, direction: Vector2
|
|
) -> Vector2:
|
|
if _velocity.y < max_velocity["fall"]:
|
|
linear_velocity.y += _gravity * delta
|
|
else:
|
|
linear_velocity.y = max_velocity["fall"]
|
|
if _velocity.x == 0:
|
|
linear_velocity.x += inair_velocity * direction.x
|
|
return linear_velocity
|
|
|
|
|
|
func calculate_wallslide_velocity(
|
|
linear_velocity: Vector2, delta: float, direction: Vector2
|
|
) -> Vector2:
|
|
# Walljump mechanics
|
|
if is_correct_walljump_input(direction):
|
|
# TODO This +0.01 indicates a larger problem with division through possible 0 values!!
|
|
var multiplicator = max(min(1, 1000 / (_velocity.y + 0.01)), 0.5)
|
|
linear_velocity.y += (
|
|
(acceleration_force["walljump"].y / mass)
|
|
* -1
|
|
* multiplicator
|
|
)
|
|
linear_velocity.x += max_velocity["walljump"] * direction.x
|
|
else:
|
|
linear_velocity.y += _gravity * delta * 0.4
|
|
# linear_velocity.x += inair_velocity * direction.x
|
|
return linear_velocity
|
|
|
|
|
|
func calculate_stomp_velocity(linear_velocity: Vector2, impulse: float) -> Vector2:
|
|
var out := linear_velocity
|
|
out.y = -impulse
|
|
return out
|
|
|
|
|
|
func execute_movement() -> void:
|
|
_velocity = move_and_slide(_velocity, FLOOR_NORMAL)
|
|
# TODO Replace .get_nodes with $ and put them to file beginning if possible
|
|
# var camera = self.get_node("Camera2D")
|
|
# if _velocity.x < 0:
|
|
# camera.transform.origin.x = -100
|
|
# if _velocity.x > 0:
|
|
# camera.transform.origin.x = 100
|
|
|
|
|
|
func die() -> void:
|
|
queue_free()
|
|
PlayerData.deaths += 1
|