Добавил преследование
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,69 @@
|
||||
extends Node3D
|
||||
# Камень преследует локального игрока, обходя препятствия по навмешу, и ловит его.
|
||||
|
||||
@export var speed := 12.0 # Скорость движения
|
||||
@export var turn_speed := 6.0 # Как быстро разворачивается к игроку
|
||||
@export var catch_distance := 3.0 # С какого расстояния (по горизонтали) ловит игрока
|
||||
@export var catch_height := 4.0 # Игрока выше этого над камнем не достать
|
||||
@export var repath_distance := 1.0 # Пересчитываем путь, когда игрок сместился на столько
|
||||
|
||||
@onready var agent: NavigationAgent3D = $NavigationAgent3D
|
||||
@onready var start_transform := global_transform
|
||||
|
||||
var player: Node3D = null
|
||||
|
||||
func _ready() -> void:
|
||||
agent.target_desired_distance = 1.0
|
||||
agent.path_desired_distance = 1.5
|
||||
agent.path_height_offset = 0.25 # Навмеш лежит чуть выше пола
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if player == null:
|
||||
player = get_tree().get_first_node_in_group("local_player") as Node3D
|
||||
if player == null:
|
||||
return
|
||||
if player.has_signal("respawned"):
|
||||
player.respawned.connect(_on_player_respawned)
|
||||
|
||||
# Пока игрок лежит — стоим над ним
|
||||
if player.get("is_dead"):
|
||||
return
|
||||
|
||||
var flat := player.global_position - global_position
|
||||
var dy := flat.y
|
||||
flat.y = 0.0
|
||||
if flat.length() <= catch_distance and absf(dy) <= catch_height:
|
||||
_face(flat, delta)
|
||||
if player.has_method("die"):
|
||||
player.die()
|
||||
return
|
||||
|
||||
var step: Vector3
|
||||
var map := agent.get_navigation_map()
|
||||
if NavigationServer3D.map_get_iteration_id(map) > 0:
|
||||
if agent.target_position.distance_to(player.global_position) > repath_distance:
|
||||
agent.target_position = player.global_position
|
||||
if not agent.is_navigation_finished():
|
||||
step = agent.get_next_path_position() - global_position
|
||||
|
||||
# Навмеш ещё не готов или игрок вне его — идём напрямую
|
||||
if step == Vector3.ZERO:
|
||||
step = flat
|
||||
|
||||
var d := step.length()
|
||||
if d < 0.001:
|
||||
return
|
||||
global_position += step / d * min(speed * delta, d)
|
||||
_face(Vector3(step.x, 0.0, step.z), delta)
|
||||
|
||||
# Игрок возродился — возвращаемся на старт, чтобы не поймать его сразу снова
|
||||
func _on_player_respawned() -> void:
|
||||
global_transform = start_transform
|
||||
agent.target_position = global_position
|
||||
|
||||
# Плавный разворот: модель смотрит вперёд по -Z
|
||||
func _face(dir: Vector3, delta: float) -> void:
|
||||
if dir.length_squared() < 0.0001:
|
||||
return
|
||||
var target_yaw := atan2(-dir.x, -dir.z)
|
||||
rotation.y = lerp_angle(rotation.y, target_yaw, 1.0 - exp(-turn_speed * delta))
|
||||
@@ -0,0 +1 @@
|
||||
uid://o2kqd0cy4knr
|
||||
Reference in New Issue
Block a user