godot-plateformer/_player/player_locomotion.gd

192 lines
5.3 KiB
GDScript3
Raw Normal View History

2025-12-29 11:54:31 +08:00
class_name CelesteLocomotionComponent extends JumpLocomotionComponent
#region 冲刺相关参数
@export_category("Dash Properties")
##最大的冲刺次数
@export var maxium_dash_count:int = 1
##Dash时的速度
@export var dash_speed: float = 240
##结束Dash的速度
@export var end_dash_speed: float = 160
##Dash的冷却时间
@export var dash_cold_down: float = .2
##是否在组件ready时自动补充所有的Dash次数
@export var auto_recover_dash_count_at_ready: bool = true
#endregion
#region 攀爬相关参数
@export_category("Climb Properties")
##角色最大耐力
@export var climb_max_stamina: float
##角色向上时的速度
@export var climb_max_speed_upward: float = 45.0
##角色向下时的速度
@export var climb_max_speed_downward: float = 80.0
##角色速度变化时的最大加速度
@export var climb_acceleration: float = 900.0
##攀爬到顶点时候的自动代偿速度X
@export var climb_hop_velocity_x: float = 80
##攀爬到顶点时候的自动代偿速度Y
@export var climb_hop_velocity_y: float = 160
##攀爬跳的速度X
@export var climb_jump_velocity_x: float = 160
##攀爬跳的速度Y
@export var climb_jump_velocity_y: float = 160
##攀爬跳的最大可输入时长
@export var climb_jump_time: float = .14
#endregion
#region 冲刺field
var last_dash_count: int
##此变量为总开关如果关闭则在物理更新里无论如何也是不会更新Dash的这里默认为false因为Dash需要手动触发最好不要常开
var can_dash: bool = false
var _dash_direction: Vector2 #存储Dash的Direction
signal dash_count_changed(count: int)
signal dash_brusted
signal dash_prepared
#endregion
#region 攀爬field
var can_climb: bool = false
var _climb_input: float
var _climb_hop_flag: bool = false
var _is_climb_jumping: bool = false
#endregion
func _init_component() -> void:
super._init_component()
if auto_recover_dash_count_at_ready:
full_recover_dash_count()
func _physics_process(delta: float) -> void:
if Engine.is_editor_hint():
return
if can_climb:
print("攀爬更新中")
_update_climb(delta)
characterbody.move_and_slide() #移动更新
return
if can_dash:
characterbody.move_and_slide()
return
super._physics_process(delta)
func _update_climb(delta) -> void:
var target_abs: float
#更新目标速度
if sign(_climb_input) == .0:
target_abs = 0
elif sign(_climb_input) > 0:
target_abs = climb_max_speed_downward
else:
target_abs = climb_max_speed_upward
var target = target_abs * _climb_input
characterbody.velocity.y = speed_approach(characterbody.velocity.y,target,climb_acceleration * delta)
func _update_dash(delta) -> void:
return
##整合之后的函数如果不需要额外的逻辑可以直接通过这个触发Dash
func integrate_dash(dash_dir: Vector2) -> bool:
if not predash(dash_dir):
return false
await get_tree().process_frame #等待一帧
brust_dash()
return true
##dash函数输入一个Dash的方向返回是否成功
func brust_dash() -> bool:
var old: Vector2 = characterbody.velocity;
var burst: Vector2 = _dash_direction.normalized() * dash_speed;
if sign(old.x) == sign(burst.x) and abs(old.x) > abs(burst.x):
burst.x = old.x
characterbody.velocity = burst
dash_brusted.emit()
return true
##dash准备函数需要在dash的前一帧触发
func predash(dash_dir: Vector2) -> bool:
if not get_can_dash():
return false
dash_prepared.emit()
last_dash_count = maxi(last_dash_count -1,0)
can_dash = true
_dash_direction = dash_dir
return true
##停止Dash实际上是关闭Dash标识符
func stop_dash(force_stop: bool = false) -> void:
if force_stop:
characterbody.velocity = Vector2.ZERO
characterbody.move_and_slide()
can_dash = false
##完全回复的Dash次数
func full_recover_dash_count() -> void:
dash_count_changed.emit(last_dash_count)
last_dash_count = maxium_dash_count
##回复指定数量的Dash次数
func recover_dash_count(recover_count : int) -> void:
last_dash_count = clampi(last_dash_count+ recover_count, 0,maxium_dash_count)
##子类可以重写此方法以自定义Dash的条件
func get_can_dash() -> bool:
return last_dash_count > 0
##添加攀爬的输入
func add_climb_input(input: float) -> bool:
_climb_input = input
return true
##开始攀爬
func start_climb(force_reset: bool = false) -> void:
if force_reset:
characterbody.velocity = Vector2.ZERO
characterbody.move_and_slide()
can_climb = true
##终止攀爬
func suspend_climb() -> void:
can_climb = false
##攀爬补充跳跃
func climb_hop() -> void:
_climb_hop_flag = true
characterbody.velocity = Vector2(climb_hop_velocity_x * Player.get_direction_vector(characterbody.direction).x,-1 * climb_hop_velocity_y)
func start_climb_jump() -> bool:
if _is_jumping : return false
#给与一个跳跃的补正速度
characterbody.velocity.x = _movement_input * climb_jump_velocity_x # 跳跃的水平补正速度
_jump_timer = climb_jump_time
_is_jumping = true
_is_climb_jumping = true
can_climb = false #取消掉原本的climb如果后续重新触发climb则重新判断
characterbody.velocity.y = _get_jump_force()
return true
func stop_climb_jump() -> void:
_is_jumping = false
_is_climb_jumping = false
func _get_jump_force() -> float:
if _is_climb_jumping:
return -1 * climb_jump_velocity_y
return super._get_jump_force()