'''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 ##跳跃时对移动输入的补正 @export var jump_countinus_horizontal_Boost : float = 200 ##是否持续的增加jump的水平补正,如果不持续,则只在跳跃的第一帧添加 @export var countinus_jump_boost: bool = true ##跳跃对移动输入的水平补正可以持续的时间 @export var jump_horizontal_Boost_last_time : float = .08 ##跳跃水平方向速度补偿的最大值,如果当前速度加补偿速度超过了这个阈值,会自动重置为该阈值 @export var max_jump_horizontal_boost_speed: float = 600 ##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 var _h_boost_timer: float ##跳跃 func jump(force_reset_x: bool = false) -> bool: if _is_jumping : return false var input_dir = sign(_movement_input) as float 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 # ---------- 情况 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("强制重置") _jump_timer = jump_hold_maxium_time _h_boost_timer = jump_horizontal_Boost_last_time _is_jumping = true characterbody.velocity.y = _get_jump_force() return true ##停止跳跃,实际的功能是重置跳跃相关的标识符 func stop_jump() -> void: # 如果还在上升,直接砍掉上升速度 if characterbody.velocity.y < 0 and _jump_timer > 0: characterbody.velocity.y *= 0.6 _jump_timer = 0 _h_boost_timer = 0 _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: #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 # --------- Continuous Jump Horizontal Boost --------- if countinus_jump_boost \ and _is_jumping \ and _h_boost_timer > 0: _h_boost_timer -= delta var input_dir := sign(_movement_input) if input_dir != 0: _apply_continuous_jump_boost(input_dir, delta) super._update_gravity(delta) ## 应用跳跃水平补偿的后的处理逻辑 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 ##重写重力乘量函数 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 if -1 * sign(_movement_input) == wall_normal_x and characterbody.is_on_wall() and characterbody.velocity.y > 0: 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