钩锁逻辑更新
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"]
|
[node name="Grapping" type="LimboState" parent="PlayerHSM/Normal/GrapHook"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
script = ExtResource("19_u7cua")
|
script = ExtResource("19_u7cua")
|
||||||
|
release_distance = 20.0
|
||||||
|
|
||||||
[node name="Dash" type="LimboState" parent="PlayerHSM/Normal"]
|
[node name="Dash" type="LimboState" parent="PlayerHSM/Normal"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
|
|
@ -184,11 +185,13 @@ metadata/_custom_type_script = "uid://bkkkyugppu7sl"
|
||||||
[node name="ReedSFXMananger" type="Node" parent="."]
|
[node name="ReedSFXMananger" type="Node" parent="."]
|
||||||
script = ExtResource("24_x5g5e")
|
script = ExtResource("24_x5g5e")
|
||||||
bindings = Array[ExtResource("25_rjd7i")]([ExtResource("26_256x0")])
|
bindings = Array[ExtResource("25_rjd7i")]([ExtResource("26_256x0")])
|
||||||
|
enable_debug = false
|
||||||
metadata/_custom_type_script = "uid://lp1ge1qbyfr3"
|
metadata/_custom_type_script = "uid://lp1ge1qbyfr3"
|
||||||
|
|
||||||
[node name="ReedVFXManager" type="Node" parent="."]
|
[node name="ReedVFXManager" type="Node" parent="."]
|
||||||
script = ExtResource("24_mwlgv")
|
script = ExtResource("24_mwlgv")
|
||||||
bindings = Array[ExtResource("25_s5egm")]([ExtResource("26_s5egm"), ExtResource("30_hquoe")])
|
bindings = Array[ExtResource("25_s5egm")]([ExtResource("26_s5egm"), ExtResource("30_hquoe")])
|
||||||
|
enable_debug = false
|
||||||
metadata/_custom_type_script = "uid://ta2r2bc1nrwe"
|
metadata/_custom_type_script = "uid://ta2r2bc1nrwe"
|
||||||
|
|
||||||
[node name="HitBox" type="Area2D" parent="."]
|
[node name="HitBox" type="Area2D" parent="."]
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,11 @@ var/had_jump/type = 1
|
||||||
var/had_jump/value = false
|
var/had_jump/value = false
|
||||||
var/had_jump/hint = 0
|
var/had_jump/hint = 0
|
||||||
var/had_jump/hint_string = ""
|
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/name = &"is_dashing"
|
||||||
var/is_dashing/type = 1
|
var/is_dashing/type = 1
|
||||||
var/is_dashing/value = false
|
var/is_dashing/value = false
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,14 @@ extends LimboState
|
||||||
@onready var root: Normal = %Normal
|
@onready var root: Normal = %Normal
|
||||||
|
|
||||||
@export_category("Hook Pull Release")
|
@export_category("Hook Pull Release")
|
||||||
|
##如果和目标点小于此距离,则会自动松开
|
||||||
@export var release_distance: float = 12.0
|
@export var release_distance: float = 12.0
|
||||||
|
##如果钩爪方向和角色速度方向小于此,则中断
|
||||||
@export var release_dot_threshold: float = 0.0
|
@export var release_dot_threshold: float = 0.0
|
||||||
|
##最短pull时间,即使距离非常近,也会判断至少此时间
|
||||||
@export var min_pull_timer: float = 0.08
|
@export var min_pull_timer: float = 0.08
|
||||||
|
##如果钩爪跳时速度低于这个值,则会强制重置跳跃
|
||||||
|
@export var force_jump_reset_maxinum_speed: float = 230
|
||||||
|
|
||||||
var _pull_timer := 0.0
|
var _pull_timer := 0.0
|
||||||
var _anchor
|
var _anchor
|
||||||
|
|
@ -75,9 +80,7 @@ func _update(delta: float) -> void:
|
||||||
return
|
return
|
||||||
|
|
||||||
func _exit() -> void:
|
func _exit() -> void:
|
||||||
agent.locomotion_comp.stop_custom_move(false)
|
agent.locomotion_comp._release_hook_keep_momentum()
|
||||||
_anchor = null
|
|
||||||
|
|
||||||
agent.spawn_hook_comp.release_cached_hook()
|
agent.spawn_hook_comp.release_cached_hook()
|
||||||
|
|
||||||
func _handle_trigger_jump() -> bool:
|
func _handle_trigger_jump() -> bool:
|
||||||
|
|
@ -85,6 +88,9 @@ func _handle_trigger_jump() -> bool:
|
||||||
return false
|
return false
|
||||||
|
|
||||||
func _hook_to_jump() -> void:
|
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)
|
get_root().blackboard.set_var(&"want_to_jump",true)
|
||||||
self.dispatch(&"hook_to_jump")
|
self.dispatch(&"hook_to_jump")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,12 @@ func _setup() -> void:
|
||||||
func _enter() -> void:
|
func _enter() -> void:
|
||||||
_jump_from_land_check()
|
_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(&"is_jumping",true) #标记jump
|
||||||
|
get_root().blackboard.set_var(&"force_reset_jump",false)#重置强制重置位
|
||||||
|
|
||||||
func _exit() -> void:
|
func _exit() -> void:
|
||||||
#这里强制重置一下
|
#这里强制重置一下
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -8,9 +8,14 @@ extends Node2D
|
||||||
@export var max_length := 200.0
|
@export var max_length := 200.0
|
||||||
@export var stretching_speed: float = 1400.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 line_2d: Line2D = %Line2D
|
||||||
@onready var ray: RayCast2D = %RayCast2D
|
@onready var ray: RayCast2D = %RayCast2D
|
||||||
|
|
||||||
|
var _tween: Tween
|
||||||
|
|
||||||
const GRAPABLE_GROUP = &"GRAPABLE"
|
const GRAPABLE_GROUP = &"GRAPABLE"
|
||||||
|
|
||||||
signal stretching_finished(reach_limit: bool, anchor_node: Node2D)
|
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)
|
stretching_finished.emit(reach_max, anchor)
|
||||||
|
|
||||||
## 釋放鉤爪(清理 Anchor 與狀態)
|
## 釋放鉤爪(清理 Anchor 與狀態)
|
||||||
func release_hook() -> void:
|
func _release_hook() -> void:
|
||||||
# 1. 停止拉伸(保險)
|
# 1. 停止拉伸(保險)
|
||||||
_is_stretching = false
|
_is_stretching = false
|
||||||
_stretching_dir = Vector2.ZERO
|
_stretching_dir = Vector2.ZERO
|
||||||
|
|
@ -145,8 +150,59 @@ func release_hook() -> void:
|
||||||
ray.target_position = Vector2.ZERO
|
ray.target_position = Vector2.ZERO
|
||||||
_update_line()
|
_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:
|
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)
|
line_2d.set_point_position(1, ray.target_position)
|
||||||
|
|
||||||
func _create_anchor_on_node(target: Node2D, hit_global_pos: Vector2) -> Node2D:
|
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:
|
func spawn_grap_hook_inst(dir: Vector2) -> Hook:
|
||||||
|
|
||||||
var i = GRAPPING_HOOK.instantiate() as Hook
|
var i = GRAPPING_HOOK.instantiate() as Hook
|
||||||
|
owner.add_child(i)
|
||||||
i.init(self,true)
|
i.init(self,true)
|
||||||
get_tree().current_scene.add_child(i)
|
|
||||||
i.start_stretching(dir)
|
i.start_stretching(dir)
|
||||||
_current_grap_hook_inst = i
|
_current_grap_hook_inst = i
|
||||||
|
|
||||||
|
|
@ -25,7 +25,7 @@ func spawn_grap_hook_inst(dir: Vector2) -> Hook:
|
||||||
|
|
||||||
func release_cached_hook() -> void:
|
func release_cached_hook() -> void:
|
||||||
if _current_grap_hook_inst:
|
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:
|
func get_current_hook_inst() -> Hook:
|
||||||
return _current_grap_hook_inst
|
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
|
if _is_jumping : return false
|
||||||
|
|
||||||
var input_dir = sign(_movement_input) as float
|
var input_dir = sign(_movement_input) as float
|
||||||
if input_dir != 0 :
|
if not force_reset_x:
|
||||||
var vel_dir := sign(characterbody.velocity.x)
|
if input_dir != 0 :
|
||||||
var accel_dir := sign(_current_acceleration.x)
|
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)
|
# ---------- 情况 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
|
_jump_timer = jump_hold_maxium_time
|
||||||
_h_boost_timer = jump_horizontal_Boost_last_time
|
_h_boost_timer = jump_horizontal_Boost_last_time
|
||||||
|
|
|
||||||
|
|
@ -12,33 +12,43 @@ func _ready() -> void:
|
||||||
_bind_all()
|
_bind_all()
|
||||||
|
|
||||||
func _bind_all() -> void:
|
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:
|
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):
|
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
|
continue
|
||||||
|
|
||||||
var target := get_node(binding.target_node)
|
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):
|
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
|
continue
|
||||||
|
|
||||||
# 🔥 关键:lambda 包一层 + 打印确认
|
|
||||||
var cb := func(ctx = null):
|
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)
|
_on_sfx_signal(binding, ctx)
|
||||||
|
|
||||||
# 防止重复连接
|
|
||||||
if target.is_connected(binding.signal_name, cb):
|
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:
|
else:
|
||||||
var err := target.connect(binding.signal_name, cb)
|
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:
|
func _on_sfx_signal(binding: SFXSignalBinding, args: Variant) -> void:
|
||||||
if enable_debug and binding.debug_print:
|
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"):
|
if args is Dictionary and args.has("world_pos"):
|
||||||
_play_at_position(binding, args["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