2025-12-29 11:54:31 +08:00
|
|
|
|
'''Agens移动控制组件
|
|
|
|
|
|
|
|
|
|
|
|
Extra:
|
|
|
|
|
|
jump() 基础的跳跃,可以往上跳跃
|
|
|
|
|
|
stop_jump() 停止跳跃
|
|
|
|
|
|
walL_jump() 墙跳
|
|
|
|
|
|
'''
|
|
|
|
|
|
class_name JumpLocomotionComponent extends LocomotionComponent
|
|
|
|
|
|
|
|
|
|
|
|
# <-- JUMP & FALL PROPOTIY -->
|
|
|
|
|
|
@export_category("Jump Properties")
|
|
|
|
|
|
##跳跃力度,在调用跳跃方法时自动处理为负,无需 * -1
|
|
|
|
|
|
@export var jump_force : float = 280
|
|
|
|
|
|
##跳跃极限时间,超过这个时间则无法继续监听跳跃输入
|
|
|
|
|
|
@export var jump_hold_maxium_time : float = .18
|
|
|
|
|
|
##跳跃时对移动输入的补正
|
|
|
|
|
|
@export var jump_horizontal_Boost : float = 80
|
2026-01-10 14:04:34 +08:00
|
|
|
|
##跳跃时对移动输入的补正
|
|
|
|
|
|
@export var jump_countinus_horizontal_Boost : float = 200
|
|
|
|
|
|
##是否持续的增加jump的水平补正,如果不持续,则只在跳跃的第一帧添加
|
|
|
|
|
|
@export var countinus_jump_boost: bool = true
|
2026-01-05 17:38:43 +08:00
|
|
|
|
##跳跃对移动输入的水平补正可以持续的时间
|
|
|
|
|
|
@export var jump_horizontal_Boost_last_time : float = .08
|
2026-01-10 14:04:34 +08:00
|
|
|
|
##跳跃水平方向速度补偿的最大值,如果当前速度加补偿速度超过了这个阈值,会自动重置为该阈值
|
|
|
|
|
|
@export var max_jump_horizontal_boost_speed: float = 600
|
2025-12-29 11:54:31 +08:00
|
|
|
|
##Jump时是否还需要受到重力影响
|
|
|
|
|
|
@export var jump_effected_by_gravity : bool = true
|
|
|
|
|
|
##半重力触发阈值,当速度小于这个数值时,会将角色的重力减半
|
|
|
|
|
|
@export var light_gravity_threshold: float = 80
|
|
|
|
|
|
##半重力乘量,默认.5
|
|
|
|
|
|
@export var light_gravity_mult: float = .5
|
|
|
|
|
|
|
|
|
|
|
|
@export_category("Wall Properties")
|
|
|
|
|
|
##如果apply,则在墙壁下滑时,会额外受到摩擦而保持wall slide speed
|
|
|
|
|
|
@export var apply_wall_slide_gravity: bool = true
|
|
|
|
|
|
##在墙壁下滑时的速度最大值
|
|
|
|
|
|
@export var wall_slide_fall_maxium_speed: float = 105
|
|
|
|
|
|
@export var wall_jump_base_force_x : float = 380
|
|
|
|
|
|
@export var wall_jump_base_force_y : float = -1
|
|
|
|
|
|
|
|
|
|
|
|
var _jump_timer : float
|
|
|
|
|
|
var _is_jumping : bool = false
|
|
|
|
|
|
var _is_wall_jumping: bool = false
|
2026-01-05 17:38:43 +08:00
|
|
|
|
var _h_boost_timer: float
|
2025-12-29 11:54:31 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##跳跃
|
2026-01-11 00:57:27 +08:00
|
|
|
|
func jump(force_reset_x: bool = false) -> bool:
|
2025-12-29 11:54:31 +08:00
|
|
|
|
if _is_jumping : return false
|
|
|
|
|
|
|
2026-01-10 14:04:34 +08:00
|
|
|
|
var input_dir = sign(_movement_input) as float
|
2026-01-11 00:57:27 +08:00
|
|
|
|
if not force_reset_x:
|
|
|
|
|
|
if input_dir != 0 :
|
|
|
|
|
|
var vel_dir := sign(characterbody.velocity.x)
|
|
|
|
|
|
var accel_dir := sign(_current_acceleration.x)
|
|
|
|
|
|
|
|
|
|
|
|
# ---------- 情况 1:角色在起步 ----------
|
|
|
|
|
|
# velocity 还没起来,但已经在往某方向加速
|
|
|
|
|
|
if vel_dir == 0 and accel_dir == input_dir:
|
|
|
|
|
|
characterbody.velocity.x += input_dir * jump_horizontal_Boost
|
|
|
|
|
|
|
|
|
|
|
|
# ---------- 情况 2:角色稳定同向移动 ----------
|
|
|
|
|
|
elif vel_dir == input_dir and accel_dir == 0:
|
|
|
|
|
|
characterbody.velocity.x += input_dir * jump_horizontal_Boost
|
2026-01-10 14:04:34 +08:00
|
|
|
|
|
2026-01-11 00:57:27 +08:00
|
|
|
|
# ---------- 情况 3:角色正在反向 / pivot ----------
|
|
|
|
|
|
elif vel_dir == -input_dir:
|
|
|
|
|
|
characterbody.velocity.x = input_dir * jump_horizontal_Boost
|
|
|
|
|
|
|
|
|
|
|
|
apply_jump_horizontal_boost(input_dir)
|
|
|
|
|
|
else:
|
|
|
|
|
|
##如果强制重置,我们会让水平速度直接等于输入加水平补正
|
|
|
|
|
|
characterbody.velocity.x = input_dir * jump_horizontal_Boost
|
|
|
|
|
|
print("强制重置")
|
2025-12-29 11:54:31 +08:00
|
|
|
|
|
|
|
|
|
|
_jump_timer = jump_hold_maxium_time
|
2026-01-05 17:38:43 +08:00
|
|
|
|
_h_boost_timer = jump_horizontal_Boost_last_time
|
2025-12-29 11:54:31 +08:00
|
|
|
|
_is_jumping = true
|
|
|
|
|
|
characterbody.velocity.y = _get_jump_force()
|
|
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
|
|
|
|
|
|
|
##停止跳跃,实际的功能是重置跳跃相关的标识符
|
|
|
|
|
|
func stop_jump() -> void:
|
2026-01-05 17:38:43 +08:00
|
|
|
|
|
|
|
|
|
|
# 如果还在上升,直接砍掉上升速度
|
|
|
|
|
|
if characterbody.velocity.y < 0 and _jump_timer > 0:
|
|
|
|
|
|
characterbody.velocity.y *= 0.6
|
|
|
|
|
|
|
|
|
|
|
|
_jump_timer = 0
|
|
|
|
|
|
_h_boost_timer = 0
|
|
|
|
|
|
|
2025-12-29 11:54:31 +08:00
|
|
|
|
_is_jumping = false
|
|
|
|
|
|
_is_wall_jumping = false
|
|
|
|
|
|
|
|
|
|
|
|
##墙跳
|
|
|
|
|
|
func wall_jump() -> void:
|
|
|
|
|
|
if not characterbody.is_on_wall_only(): return
|
|
|
|
|
|
|
|
|
|
|
|
characterbody.velocity.x = characterbody.get_wall_normal().x * wall_jump_base_force_x #基础的wall jump force
|
|
|
|
|
|
characterbody.velocity.y = _get_jump_force()
|
|
|
|
|
|
_jump_timer = jump_hold_maxium_time
|
|
|
|
|
|
_is_jumping = true
|
|
|
|
|
|
_is_wall_jumping = true
|
|
|
|
|
|
|
|
|
|
|
|
func _update_gravity(delta: float) -> void:
|
2026-01-05 17:38:43 +08:00
|
|
|
|
#if _jump_timer >= 0:
|
|
|
|
|
|
#if _is_jumping:
|
|
|
|
|
|
#characterbody.velocity.y = _get_jump_force()
|
|
|
|
|
|
#_jump_timer -= delta
|
|
|
|
|
|
#
|
|
|
|
|
|
##如果不希望jump时受到重力影响,可以关闭此开关
|
|
|
|
|
|
#if not jump_effected_by_gravity: return
|
|
|
|
|
|
if _jump_timer > 0 and _is_jumping:
|
|
|
|
|
|
_jump_timer -= delta
|
|
|
|
|
|
|
2026-01-10 14:04:34 +08:00
|
|
|
|
# --------- Continuous Jump Horizontal Boost ---------
|
|
|
|
|
|
if countinus_jump_boost \
|
|
|
|
|
|
and _is_jumping \
|
|
|
|
|
|
and _h_boost_timer > 0:
|
|
|
|
|
|
|
2026-01-05 17:38:43 +08:00
|
|
|
|
_h_boost_timer -= delta
|
2026-01-10 14:04:34 +08:00
|
|
|
|
|
|
|
|
|
|
var input_dir := sign(_movement_input)
|
|
|
|
|
|
if input_dir != 0:
|
|
|
|
|
|
_apply_continuous_jump_boost(input_dir, delta)
|
2025-12-29 11:54:31 +08:00
|
|
|
|
|
|
|
|
|
|
super._update_gravity(delta)
|
|
|
|
|
|
|
2026-01-10 14:04:34 +08:00
|
|
|
|
## 应用跳跃水平补偿的后的处理逻辑
|
|
|
|
|
|
func apply_jump_horizontal_boost(input_dir: float) -> void:
|
|
|
|
|
|
var boost_vel := input_dir * jump_horizontal_Boost
|
|
|
|
|
|
var current_vel := characterbody.velocity.x
|
|
|
|
|
|
|
|
|
|
|
|
# 只处理「同方向」的情况
|
|
|
|
|
|
if sign(current_vel) == input_dir:
|
|
|
|
|
|
if abs(current_vel) > max_jump_horizontal_boost_speed:
|
|
|
|
|
|
characterbody.velocity.x = boost_vel
|
|
|
|
|
|
|
|
|
|
|
|
func _apply_continuous_jump_boost(input_dir: float, delta: float) -> void:
|
|
|
|
|
|
var current_vel := characterbody.velocity.x
|
|
|
|
|
|
var max_vel := input_dir * max_jump_horizontal_boost_speed
|
|
|
|
|
|
|
|
|
|
|
|
# 如果已经超过最大值(极少数情况),直接截断
|
|
|
|
|
|
if sign(current_vel) == input_dir and abs(current_vel) > abs(max_vel):
|
|
|
|
|
|
characterbody.velocity.x = max_vel
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
# 只有在“同方向”或“静止”时,才允许继续加速
|
|
|
|
|
|
if current_vel == 0 or sign(current_vel) == input_dir:
|
|
|
|
|
|
characterbody.velocity.x += input_dir * jump_countinus_horizontal_Boost * delta
|
|
|
|
|
|
|
2025-12-29 11:54:31 +08:00
|
|
|
|
##重写重力乘量函数
|
|
|
|
|
|
func _get_gravity_scale() -> float:
|
|
|
|
|
|
var c = absf(characterbody.velocity.y) <= light_gravity_threshold && _is_jumping
|
|
|
|
|
|
return light_gravity_mult if c else default_gravity_scale
|
|
|
|
|
|
|
|
|
|
|
|
##重写最大下落速度
|
|
|
|
|
|
func _get_max_fall_speed() -> float:
|
|
|
|
|
|
var wall_normal_x = characterbody.get_wall_normal().x
|
2026-01-11 22:32:09 +08:00
|
|
|
|
if -1 * sign(_movement_input) == wall_normal_x and characterbody.is_on_wall() and characterbody.velocity.y > 0:
|
2025-12-29 11:54:31 +08:00
|
|
|
|
return wall_slide_fall_maxium_speed
|
|
|
|
|
|
else:
|
|
|
|
|
|
return fall_maxium_speed
|
|
|
|
|
|
|
|
|
|
|
|
##设定jump的力度
|
|
|
|
|
|
func _get_jump_force() -> float:
|
|
|
|
|
|
var result: float = jump_force
|
|
|
|
|
|
if _is_wall_jumping and wall_jump_base_force_y > 0:
|
|
|
|
|
|
result = wall_jump_base_force_y
|
|
|
|
|
|
return -1.0 * result
|