Files
SECAS_game/libs/character_movement.gd
T

229 lines
5.7 KiB
GDScript

extends Node
enum MovementType {
PLATFORMER,
TOP_DOWN,
CUSTOM,
NONE
}
enum DashType {
KEYS,
HORIZONTAL_KEYS,
MOUSE,
CONTINOUS_MOUSE,
SPRINT,
NONE
}
class CharMovement:
var movement_type: MovementType
var custom_movement_func: Callable = Callable()
# EXTRA (that may or may not be added)
# Coyote time
# Input buffer
# Params
var speed: float
var sprint_speed: float
var jump_power: float
var extra_jumps: int
var coyote_time: float
var jump_buffer_time: float
var dash_type: DashType
var aerial_dash_count: int
var vel_multiplier_after_dash: float
var dash_speed: float
var dash_dur: float
var dash_cd: float
# Physics Params
var gravity: float
var terminal_vel: float
# Updating
var velocity: Vector2 = Vector2.ZERO
var is_grounded: bool = false
var can_jump: bool = true
var can_move: bool = true
var jumps: int = 0
var coyote_timer: float = 0.0
var jump_buffer_timer: float = 0.0
var is_dashing: bool = false
var is_dash_cd: bool = false
var dash_timer: float = 0.0
var dash_cd_timer: float = 0.0
var aerial_dashes: int = 0
var look_dir: Vector2 = Vector2.ZERO
var last_look_dir: Vector2 = Vector2.ZERO
var move_dir: Vector2 = Vector2.ZERO
var move_dir_x: float = 0.0
var last_move_dir: Vector2 = Vector2.ZERO
var last_move_dir_x: float = 0.0
var was_dash_pressed: bool = false
var was_jump_pressed: bool = false
var is_jump_held: bool = false
func _init(
_movement_type: MovementType,
_speed: float,
_sprint_speed: float,
_jump_power: float,
_extra_jumps: int,
_coyote_time: float,
_jump_buffer_time: float,
_dash_type: DashType,
_aerial_dash_count: int,
_vel_multiplier_after_dash: float,
_dash_speed: float,
_dash_dur: float,
_dash_cd: float,
_gravity: float,
_terminal_vel: float
):
movement_type = _movement_type
speed = _speed
sprint_speed = _sprint_speed
jump_power = _jump_power
extra_jumps = _extra_jumps
coyote_time = _coyote_time
dash_type = _dash_type
dash_speed = _dash_speed
dash_dur = _dash_dur
dash_cd = _dash_cd
gravity = _gravity
terminal_vel = _terminal_vel
# Long names
jump_buffer_time = _jump_buffer_time
aerial_dash_count = _aerial_dash_count
vel_multiplier_after_dash = _vel_multiplier_after_dash
func set_custom_movement_func(function: Callable):
custom_movement_func = function
func process(_look_dir: Vector2, _delta: float):
look_dir = _look_dir
move_dir = Input.get_vector("left", "right", "up", "down")
move_dir_x = Input.get_axis("left", "right")
was_dash_pressed = Input.is_action_just_pressed("dash")
was_jump_pressed = Input.is_action_just_pressed("jump")
is_jump_held = Input.is_action_pressed("jump")
if movement_type == MovementType.PLATFORMER:
was_jump_pressed = was_jump_pressed || Input.is_action_just_pressed("jump_alt")
is_jump_held = is_jump_held || Input.is_action_pressed("jump_alt")
func phys_process(delta: float):
move_logic(delta)
jump_logic(delta)
# dash overrides other movement
dash_logic(delta)
physics(delta)
func dash_logic(delta: float):
if is_grounded: aerial_dashes = 0
if was_dash_pressed && !is_dashing && !is_dash_cd:
if movement_type == MovementType.TOP_DOWN \
|| aerial_dashes < aerial_dash_count \
|| is_grounded:
is_dashing = true
last_look_dir = look_dir
last_move_dir = move_dir
last_move_dir_x = move_dir_x
aerial_dashes += 1
if is_dashing:
dash_timer += delta
dash_velocity(delta)
if dash_timer >= dash_dur:
is_dashing = false
is_dash_cd = true
dash_timer = 0.0
velocity *= vel_multiplier_after_dash
if is_dash_cd:
dash_cd_timer += delta
if dash_cd_timer >= dash_cd:
is_dash_cd = false
dash_cd_timer = 0.0
func dash_velocity(delta: float):
match dash_type:
DashType.KEYS: velocity = last_move_dir * dash_speed * delta
DashType.HORIZONTAL_KEYS: velocity.x = last_move_dir_x * dash_speed * delta
DashType.MOUSE: velocity = last_look_dir * dash_speed * delta
DashType.CONTINOUS_MOUSE: velocity = look_dir * dash_speed * delta
DashType.SPRINT: pass
DashType.NONE: pass
func move_logic(delta: float):
if can_move: movement_velocity(delta)
func movement_velocity(delta: float):
var final_speed = speed
if dash_type == DashType.SPRINT && Input.is_action_pressed("dash"):
final_speed = sprint_speed
match movement_type:
MovementType.TOP_DOWN: velocity = move_dir * final_speed * delta
MovementType.PLATFORMER: velocity.x = move_dir_x * final_speed * delta
MovementType.CUSTOM: custom_movement_func.call(delta)
MovementType.NONE: pass
func jump_logic(delta: float):
if is_grounded: jumps = 0
if !can_jump || movement_type != MovementType.PLATFORMER: return
# Spaghetti restaurant: $0.0 for 1 spaghett
if is_grounded && was_jump_pressed: jump()
elif coyote_timer < coyote_time \
&& was_jump_pressed && jumps == 0: jump()
elif jumps <= extra_jumps \
&& !is_grounded && was_jump_pressed: jump()
elif is_jump_held && is_grounded \
&& jump_buffer_timer < jump_buffer_time:
jumps = 0; jump()
if !is_grounded \
&& coyote_timer < coyote_time:
coyote_timer += delta
if is_jump_held && !is_grounded \
&& jump_buffer_timer < jump_buffer_time:
jump_buffer_timer += delta
if is_grounded:
coyote_timer = 0.0
if !is_jump_held: jump_buffer_timer = 0.0
func jump():
velocity.y = jump_power * -1.0
jumps += 1
func physics(delta: float):
if movement_type != MovementType.PLATFORMER: return
if !is_grounded:
velocity.y += gravity * delta
velocity.y = min(velocity.y, terminal_vel * delta)
else:
velocity.y = min(0, velocity.y)