Добавил преследование

This commit is contained in:
2026-10-27 14:57:54 +05:00
parent 6b34b8593f
commit 823d68ffd6
10 changed files with 242 additions and 18 deletions
+69
View File
@@ -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))