钩锁逻辑更新
This commit is contained in:
parent
8d3a3da5d5
commit
b57104481a
|
|
@ -139,6 +139,7 @@ grap_hook_shooting_time = 0.2
|
|||
[node name="Grapping" type="LimboState" parent="PlayerHSM/Normal/GrapHook"]
|
||||
unique_name_in_owner = true
|
||||
script = ExtResource("19_u7cua")
|
||||
release_distance = 20.0
|
||||
|
||||
[node name="Dash" type="LimboState" parent="PlayerHSM/Normal"]
|
||||
unique_name_in_owner = true
|
||||
|
|
@ -184,11 +185,13 @@ metadata/_custom_type_script = "uid://bkkkyugppu7sl"
|
|||
[node name="ReedSFXMananger" type="Node" parent="."]
|
||||
script = ExtResource("24_x5g5e")
|
||||
bindings = Array[ExtResource("25_rjd7i")]([ExtResource("26_256x0")])
|
||||
enable_debug = false
|
||||
metadata/_custom_type_script = "uid://lp1ge1qbyfr3"
|
||||
|
||||
[node name="ReedVFXManager" type="Node" parent="."]
|
||||
script = ExtResource("24_mwlgv")
|
||||
bindings = Array[ExtResource("25_s5egm")]([ExtResource("26_s5egm"), ExtResource("30_hquoe")])
|
||||
enable_debug = false
|
||||
metadata/_custom_type_script = "uid://ta2r2bc1nrwe"
|
||||
|
||||
[node name="HitBox" type="Area2D" parent="."]
|
||||
|
|
|
|||
|
|
@ -11,6 +11,11 @@ var/had_jump/type = 1
|
|||
var/had_jump/value = false
|
||||
var/had_jump/hint = 0
|
||||
var/had_jump/hint_string = ""
|
||||
var/force_reset_jump/name = &"force_reset_jump"
|
||||
var/force_reset_jump/type = 1
|
||||
var/force_reset_jump/value = false
|
||||
var/force_reset_jump/hint = 0
|
||||
var/force_reset_jump/hint_string = ""
|
||||
var/is_dashing/name = &"is_dashing"
|
||||
var/is_dashing/type = 1
|
||||
var/is_dashing/value = false
|
||||
|
|
|
|||
|
|
@ -3,9 +3,14 @@ extends LimboState
|
|||
@onready var root: Normal = %Normal
|
||||
|
||||
@export_category("Hook Pull Release")
|
||||
##如果和目标点小于此距离,则会自动松开
|
||||
@export var release_distance: float = 12.0
|
||||
##如果钩爪方向和角色速度方向小于此,则中断
|
||||
@export var release_dot_threshold: float = 0.0
|
||||
##最短pull时间,即使距离非常近,也会判断至少此时间
|
||||
@export var min_pull_timer: float = 0.08
|
||||
##如果钩爪跳时速度低于这个值,则会强制重置跳跃
|
||||
@export var force_jump_reset_maxinum_speed: float = 230
|
||||
|
||||
var _pull_timer := 0.0
|
||||
var _anchor
|
||||
|
|
@ -75,9 +80,7 @@ func _update(delta: float) -> void:
|
|||
return
|
||||
|
||||
func _exit() -> void:
|
||||
agent.locomotion_comp.stop_custom_move(false)
|
||||
_anchor = null
|
||||
|
||||
agent.locomotion_comp._release_hook_keep_momentum()
|
||||
agent.spawn_hook_comp.release_cached_hook()
|
||||
|
||||
func _handle_trigger_jump() -> bool:
|
||||
|
|
@ -85,6 +88,9 @@ func _handle_trigger_jump() -> bool:
|
|||
return false
|
||||
|
||||
func _hook_to_jump() -> void:
|
||||
var v : float = agent.velocity.length()
|
||||
if v <= force_jump_reset_maxinum_speed:
|
||||
get_root().blackboard.set_var(&"force_reset_jump",true)
|
||||
get_root().blackboard.set_var(&"want_to_jump",true)
|
||||
self.dispatch(&"hook_to_jump")
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,12 @@ func _setup() -> void:
|
|||
func _enter() -> void:
|
||||
_jump_from_land_check()
|
||||
|
||||
var _j = agent.locomotion_comp.jump() as bool
|
||||
##是否要强制重置水平速度。
|
||||
var f = blackboard.get_var(&"force_reset_jump",false) as bool
|
||||
var _j = agent.locomotion_comp.jump(f) as bool
|
||||
|
||||
get_root().blackboard.set_var(&"is_jumping",true) #标记jump
|
||||
get_root().blackboard.set_var(&"force_reset_jump",false)#重置强制重置位
|
||||
|
||||
func _exit() -> void:
|
||||
#这里强制重置一下
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -8,9 +8,14 @@ extends Node2D
|
|||
@export var max_length := 200.0
|
||||
@export var stretching_speed: float = 1400.0
|
||||
|
||||
@export_category("Hook Retract")
|
||||
@export var retract_speed: float = 1800.0
|
||||
|
||||
@onready var line_2d: Line2D = %Line2D
|
||||
@onready var ray: RayCast2D = %RayCast2D
|
||||
|
||||
var _tween: Tween
|
||||
|
||||
const GRAPABLE_GROUP = &"GRAPABLE"
|
||||
|
||||
signal stretching_finished(reach_limit: bool, anchor_node: Node2D)
|
||||
|
|
@ -127,7 +132,7 @@ func _handle_hit(target: Node2D, hit_pos: Vector2) -> void:
|
|||
stretching_finished.emit(reach_max, anchor)
|
||||
|
||||
## 釋放鉤爪(清理 Anchor 與狀態)
|
||||
func release_hook() -> void:
|
||||
func _release_hook() -> void:
|
||||
# 1. 停止拉伸(保險)
|
||||
_is_stretching = false
|
||||
_stretching_dir = Vector2.ZERO
|
||||
|
|
@ -145,8 +150,59 @@ func release_hook() -> void:
|
|||
ray.target_position = Vector2.ZERO
|
||||
_update_line()
|
||||
|
||||
func release_hook_with_transition(has_trans: bool) -> void:
|
||||
# 先停止一切拉伸逻辑
|
||||
_is_stretching = false
|
||||
_stretching_dir = Vector2.ZERO
|
||||
_cached_cancel = false
|
||||
|
||||
# 如果不需要动画,直接释放
|
||||
if not has_trans:
|
||||
_release_hook()
|
||||
queue_free()
|
||||
return
|
||||
|
||||
# ===== 需要回收动画 =====
|
||||
# 先清 Anchor(但不影响末端视觉)
|
||||
if _anchor and is_instance_valid(_anchor):
|
||||
_anchor.get_parent().remove_child(_anchor)
|
||||
_anchor.queue_free()
|
||||
_anchor = null
|
||||
|
||||
# 当前末端位置(本地坐标)
|
||||
var start_pos: Vector2 = ray.target_position
|
||||
var distance := start_pos.length()
|
||||
|
||||
if distance <= 0.001:
|
||||
queue_free()
|
||||
return
|
||||
|
||||
# 根据速度算 tween 时间
|
||||
var duration := distance / retract_speed
|
||||
|
||||
if _tween and _tween.is_valid():
|
||||
_tween.kill()
|
||||
|
||||
_tween = get_tree().create_tween()
|
||||
_tween.set_trans(Tween.TRANS_SINE)
|
||||
_tween.set_ease(Tween.EASE_IN)
|
||||
|
||||
_tween.tween_property(
|
||||
ray,
|
||||
"target_position",
|
||||
Vector2.ZERO,
|
||||
duration
|
||||
)
|
||||
|
||||
_tween.finished.connect(func():
|
||||
queue_free()
|
||||
)
|
||||
|
||||
func _update_line() -> void:
|
||||
line_2d.set_point_position(0, Vector2.ZERO)
|
||||
if _anchor and is_instance_valid(_anchor):
|
||||
# 关键:锚点是世界坐标固定的,把它换算到 Hook 的本地坐标
|
||||
ray.target_position = to_local(_anchor.global_position)
|
||||
|
||||
line_2d.set_point_position(1, ray.target_position)
|
||||
|
||||
func _create_anchor_on_node(target: Node2D, hit_global_pos: Vector2) -> Node2D:
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ signal hook_reach_finished(reach_limit: float, anchor: Node2D)
|
|||
func spawn_grap_hook_inst(dir: Vector2) -> Hook:
|
||||
|
||||
var i = GRAPPING_HOOK.instantiate() as Hook
|
||||
owner.add_child(i)
|
||||
i.init(self,true)
|
||||
get_tree().current_scene.add_child(i)
|
||||
i.start_stretching(dir)
|
||||
_current_grap_hook_inst = i
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ func spawn_grap_hook_inst(dir: Vector2) -> Hook:
|
|||
|
||||
func release_cached_hook() -> void:
|
||||
if _current_grap_hook_inst:
|
||||
_current_grap_hook_inst.release_hook()
|
||||
_current_grap_hook_inst.release_hook_with_transition(true)
|
||||
|
||||
func get_current_hook_inst() -> Hook:
|
||||
return _current_grap_hook_inst
|
||||
|
|
|
|||
|
|
@ -45,28 +45,33 @@ var _h_boost_timer: float
|
|||
|
||||
|
||||
##跳跃
|
||||
func jump() -> bool:
|
||||
func jump(force_reset_x: bool = false) -> bool:
|
||||
if _is_jumping : return false
|
||||
|
||||
var input_dir = sign(_movement_input) as float
|
||||
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
|
||||
if not force_reset_x:
|
||||
if input_dir != 0 :
|
||||
var vel_dir := sign(characterbody.velocity.x)
|
||||
var accel_dir := sign(_current_acceleration.x)
|
||||
|
||||
apply_jump_horizontal_boost(input_dir)
|
||||
# ---------- 情况 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
|
||||
|
|
|
|||
|
|
@ -12,33 +12,43 @@ func _ready() -> void:
|
|||
_bind_all()
|
||||
|
||||
func _bind_all() -> void:
|
||||
print("[SFX] binding count =", bindings.size(), " manager path=", get_path())
|
||||
_dbg_fmt("binding count=%d manager=%s", [bindings.size(), get_path()])
|
||||
|
||||
for binding in bindings:
|
||||
print("[SFX] try bind: target_node=", binding.target_node, " signal=", binding.signal_name)
|
||||
_dbg_fmt(
|
||||
"try bind: target_node=%s signal=%s",
|
||||
[binding.target_node, binding.signal_name]
|
||||
)
|
||||
|
||||
if not has_node(binding.target_node):
|
||||
push_warning("[SFX] target node not found: %s (manager=%s)" % [binding.target_node, get_path()])
|
||||
push_warning(
|
||||
"[SFX] target node not found: %s (manager=%s)"
|
||||
% [binding.target_node, get_path()]
|
||||
)
|
||||
continue
|
||||
|
||||
var target := get_node(binding.target_node)
|
||||
print("[SFX] target resolved:", target, " path=", target.get_path())
|
||||
_dbg_fmt("target resolved: %s path=%s", [target, target.get_path()])
|
||||
|
||||
if not target.has_signal(binding.signal_name):
|
||||
push_warning("[SFX] signal not found: %s on %s" % [binding.signal_name, target.get_path()])
|
||||
push_warning(
|
||||
"[SFX] signal not found: %s on %s"
|
||||
% [binding.signal_name, target.get_path()]
|
||||
)
|
||||
continue
|
||||
|
||||
# 🔥 关键:lambda 包一层 + 打印确认
|
||||
var cb := func(ctx = null):
|
||||
print("[SFX] callback fired! binding=", binding, " ctx=", ctx)
|
||||
_dbg_fmt(
|
||||
"callback fired: binding=%s ctx=%s",
|
||||
[binding, ctx]
|
||||
)
|
||||
_on_sfx_signal(binding, ctx)
|
||||
|
||||
# 防止重复连接
|
||||
if target.is_connected(binding.signal_name, cb):
|
||||
print("[SFX] already connected, skip:", binding.signal_name)
|
||||
_dbg_fmt("already connected: %s", [binding.signal_name])
|
||||
else:
|
||||
var err := target.connect(binding.signal_name, cb)
|
||||
print("[SFX] connect result =", err, " (OK=0)")
|
||||
_dbg_fmt("connect result=%d (OK=0)", [err])
|
||||
|
||||
func _on_sfx_signal(binding: SFXSignalBinding, args: Variant) -> void:
|
||||
if enable_debug and binding.debug_print:
|
||||
|
|
@ -52,6 +62,16 @@ func _on_sfx_signal(binding: SFXSignalBinding, args: Variant) -> void:
|
|||
if args is Dictionary and args.has("world_pos"):
|
||||
_play_at_position(binding, args["world_pos"])
|
||||
|
||||
func _dbg(msg: String) -> void:
|
||||
if not enable_debug:
|
||||
return
|
||||
print("[SFX]", msg)
|
||||
|
||||
func _dbg_fmt(fmt: String, args: Array = []) -> void:
|
||||
if not enable_debug:
|
||||
return
|
||||
print("[SFX]", fmt % args)
|
||||
|
||||
# -----------------------------
|
||||
# 播放逻辑
|
||||
# -----------------------------
|
||||
|
|
|
|||
Loading…
Reference in New Issue