104 lines
3.0 KiB
GDScript
104 lines
3.0 KiB
GDScript
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)
|