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