112 lines
2.8 KiB
GDScript
112 lines
2.8 KiB
GDScript
extends CharacterBody2D
|
||
|
||
@onready var player_collectable_volumn: PlayerTriggerVolumn = %PlayerCollectableVolumn
|
||
@onready var hook_attract_volumn: Area2D = %HookAttractVolumn
|
||
@export var respawn_time: float = 2.0
|
||
|
||
enum State {
|
||
IDLE,
|
||
PULLED_BY_HOOK,
|
||
COLLECTED
|
||
}
|
||
|
||
var _current_state: State = State.IDLE
|
||
var _spawn_position: Vector2
|
||
|
||
## 拉回速度
|
||
@export var pull_speed: float = 800.0
|
||
## 拉回目标(玩家)
|
||
var _pull_target: Node2D
|
||
|
||
func _ready() -> void:
|
||
_spawn_position = global_position
|
||
player_collectable_volumn.player_entered.connect(_on_player_collected)
|
||
|
||
##状态管理函数
|
||
func change_state(in_state: State) -> void:
|
||
if in_state == _current_state:
|
||
return
|
||
|
||
## 退出State的逻辑
|
||
match _current_state:
|
||
State.IDLE:
|
||
pass
|
||
State.PULLED_BY_HOOK:
|
||
pass
|
||
State.COLLECTED:
|
||
pass
|
||
|
||
_current_state = in_state
|
||
|
||
## 进入State的逻辑
|
||
match in_state:
|
||
State.IDLE:
|
||
pass
|
||
State.PULLED_BY_HOOK:
|
||
pass
|
||
State.COLLECTED:
|
||
_on_collected_enter()
|
||
|
||
## 钩爪击中时调用(hit_pos 是击中点,hook 是钩爪实例)
|
||
func on_hook_hit(hit_pos: Vector2, hook: Hook) -> void:
|
||
# 通过钩爪组件获取发射者(玩家)
|
||
_pull_target = hook._binded_hook_comp.owner as Node2D
|
||
if _pull_target:
|
||
change_state(State.PULLED_BY_HOOK)
|
||
|
||
func _physics_process(delta: float) -> void:
|
||
if _current_state == State.PULLED_BY_HOOK and _pull_target:
|
||
var direction := (_pull_target.global_position - global_position).normalized()
|
||
velocity = direction * pull_speed
|
||
move_and_slide()
|
||
|
||
func get_attraction_force(pos: Vector2) -> Vector2:
|
||
# 返回 (direction, strength) 格式
|
||
var dir := (global_position - pos).normalized()
|
||
var strength := 1500 # 调整这个值控制吸引力转向速度
|
||
return dir * strength
|
||
|
||
##如果玩家进入收集区域,则切换为已收集状态。
|
||
func _on_player_collected(body:CharacterBody2D) -> void:
|
||
if body is Player:
|
||
body.hsm.dispatch(&"trigger_external_dash")
|
||
change_state(State.COLLECTED)
|
||
|
||
func _on_collected_enter() -> void:
|
||
velocity = Vector2.ZERO
|
||
|
||
# 隐藏
|
||
visible = false
|
||
set_physics_process(false)
|
||
|
||
# 关闭碰撞
|
||
if has_node("CollisionShape2D"):
|
||
$CollisionShape2D.disabled = true
|
||
|
||
player_collectable_volumn.monitoring = false
|
||
player_collectable_volumn.monitorable = false
|
||
hook_attract_volumn.monitoring = false
|
||
hook_attract_volumn.monitorable = false
|
||
|
||
# 启动重生流程
|
||
_respawn_after_delay()
|
||
|
||
func _respawn_after_delay() -> void:
|
||
await get_tree().create_timer(respawn_time).timeout
|
||
|
||
global_position = _spawn_position
|
||
|
||
visible = true
|
||
set_physics_process(true)
|
||
|
||
if has_node("CollisionShape2D"):
|
||
$CollisionShape2D.disabled = false
|
||
|
||
player_collectable_volumn.monitoring = true
|
||
player_collectable_volumn.monitorable = true
|
||
hook_attract_volumn.monitoring = true
|
||
hook_attract_volumn.monitorable = true
|
||
|
||
change_state(State.IDLE)
|
||
|