class_name GrappingHook extends Node2D @export var min_rope_length := 20 @export var max_rope_length := 200 @onready var anchor: StaticBody2D = %Anchor @onready var pin_joint_2d: PinJoint2D = %PinJoint2D @onready var player_anchor: RigidBody2D = %PlayerAnchor @onready var line_2d: Line2D = %Line2D const speed = 30 var _binded_hook_comp:SpawnHookComponet var m_update_rope_with_nodes: bool = false func init(hook_comp:SpawnHookComponet): _binded_hook_comp = hook_comp ##默认以PLAYER类开始Hook func start_hook(hookPosition): anchor.global_position = hookPosition var player = get_tree().get_first_node_in_group("PLAYER") as CharacterBody2D player_anchor.global_position = player.global_position player.reparent(player_anchor) ##以注册者开始Hook func start_hook_with_instigator(hookPosition:Vector2,instigator:Node2D): anchor.global_position = hookPosition var i = instigator if not i: return player_anchor.global_position = i.global_position i.reparent(player_anchor) ##离开Hook func _leave_rope(): await get_tree().create_timer(.1).timeout var player: Node2D if _binded_hook_comp: player = _binded_hook_comp.component_owner player.reparent(get_tree().current_scene) #player.set_active(true) player.rotation = 0 queue_free() ##此函數通過外部的修改可以驅動物體在繩子上移動。 func move_hook(input_dir: Vector2, delta: float) -> void: if input_dir == Vector2.ZERO: return var distance_to_anchor := player_anchor.global_position.distance_to(anchor.global_position) # === 左右摆动(切向力)=== if input_dir.x != 0.0: var tangent := player_anchor.global_transform.x player_anchor.apply_central_impulse( tangent * input_dir.x * speed * delta ) # === 上下:改变绳长 === if input_dir.y != 0.0: # y < 0 → 上(收绳) # y > 0 → 下(放绳) var rope_dir := player_anchor.global_transform.y as Vector2 var rope_delta := rope_dir * input_dir.y * speed * delta * 0.5 as Vector2 if input_dir.y > 0.0 and distance_to_anchor >= max_rope_length: return if input_dir.y < 0.0 and distance_to_anchor <= min_rope_length: return # 暂时解绑 joint,手动移动 anchor pin_joint_2d.node_b = NodePath("") player_anchor.global_position += rope_delta pin_joint_2d.node_b = player_anchor.get_path() ##更新特定点的位置 func update_line_target_pos_with_index(point_index: int, target_pos: Vector2) -> void: line_2d.set_point_position( point_index, target_pos - global_position ) ##更新锚点的位置 func update_line_anchor_pos(target_pos: Vector2) -> void: update_line_target_pos_with_index(0,target_pos) ##重置所有点的位置到指定的位置 func reset_line_points_to_target(target_pos: Vector2)-> void: for i in range(line_2d.points.size()): update_line_target_pos_with_index(i, target_pos) func _process(delta: float) -> void: ##如果不更新,直接返回。 if not m_update_rope_with_nodes: return update_line_target_pos_with_index(0,player_anchor.global_position) update_line_target_pos_with_index(1,anchor.global_position)