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

145 lines
3.8 KiB
GDScript
Raw 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 Hook extends Node2D
## ================
## Export Field
## ================
@export var min_length := 140
@export var max_length := 200
@export var streching_speed:float = 1400
## 线段
@onready var line_2d: Line2D = %Line2D
## 检测碰撞的区域
@onready var area_2d: Area2D = %Area2D
const GRAPABLE_GROUP = &"GRAPABLE"
const ANCHOR_NODE = preload("uid://dfm5wy1rmci68")
signal stretching_finished(reach_limit:bool, anchor_node: Node2D)
## ================
## Private Field
## ================
var _binded_hook_comp
var _is_stretching: bool = false
var _stretching_dir: Vector2 = Vector2.ZERO
var _cached_cancel: bool = false
var _anchor: Node2D
func _ready() -> void:
area_2d.position = Vector2.ZERO
area_2d.area_entered.connect(grap_detected)
area_2d.body_entered.connect(grap_detected)
##初始化
func init(hook_comp:SpawnHookComponet,reset_to_target: bool):
_binded_hook_comp = hook_comp
if reset_to_target:
var p : Vector2= hook_comp.owner.global_position
self.global_position = p
##开始stretching
func start_stretching(direction: Vector2) -> void:
_is_stretching = true
_cached_cancel = false
_stretching_dir = direction
##结束stretching
func end_stretching(force_end: bool = false) -> bool:
##如果还没有达到最短的stretching length则继续
if not force_end and _is_stretching:
var d = self.global_position.distance_to(area_2d.global_position)
if d < min_length:
_cached_cancel = true
return false
_is_stretching = false
_stretching_dir = Vector2.ZERO
return true
##是否正在stretching
func is_stretching() -> bool:
return _is_stretching
##物理更新
func _physics_process(delta: float) -> void:
if _is_stretching:
_update_stretching(delta)
##更新绳索的动画表现
func _process(delta: float) -> void:
update_line_target_pos_with_index(0,self.global_position)
update_line_target_pos_with_index(1,area_2d.global_position)
##更新钩爪爪手的位置
func _update_stretching(delta: float) -> void:
var d = self.global_position.distance_to(area_2d.global_position)
#如果已经存在一个缓存的取消,且当前的长度小于最小长度,则直接取消
if _cached_cancel:
if d >= min_length:
stretching_finished.emit(true,null)
end_stretching(true)
return
#如果达到的最大的长度,直接取消
if d > max_length:
stretching_finished.emit(true,null)
end_stretching(true)
return
area_2d.global_position += delta * streching_speed * _stretching_dir
## ================
## Tool Func
## ================
##更新特定点的位置
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
)
##当触碰到可以被抓握的Area后自动在当前位置生成一个钩爪锚点后续的移动交给其他系统
func grap_detected(node: Node2D) -> void:
if node.is_in_group(GRAPABLE_GROUP):
end_stretching(true)
var d : float= self.global_position.distance_to(area_2d.global_position)
var b = d == max_length
var anchor := _create_anchor_on_node(node)
if anchor:
stretching_finished.emit(b,anchor)
##创建钩爪锚点
func _create_anchor_on_node(area: Node2D) -> Node2D:
# 如果之前有锚点,先清掉
if _anchor and is_instance_valid(_anchor):
_anchor.queue_free()
# 1. 创建 Anchor
_anchor = Node2D.new()
_anchor.name = "Anchor"
add_child(_anchor)
# 2. Anchor 初始位置 = Area 当前世界位置
_anchor.global_position = area.global_position
# 3. 在 Area 上挂 RemoteTransform2D
var remote := RemoteTransform2D.new()
remote.name = "AnchorRemote"
area.add_child(remote)
remote.remote_path = _anchor.get_path()
# 4. 只同步位置(锚点一般不需要跟旋转/缩放)
remote.update_rotation = false
remote.update_scale = false
return _anchor