godot-plateformer/addons/reedcomponent/grap_hook/grapping_hook.gd

104 lines
3.0 KiB
GDScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)