Загрузка данных


extends CharacterBody3D

@export var SPEED: float = 12.0
@export var DASH_SPEED: float = 28.0
@export var GRAVITY: float = 20.0

# Чувствительность мыши (подбери под себя)
@export var MOUSE_SENSITIVITY: float = 0.003

# Ограничения наклона камеры вверх/вниз (в радианах)
@export var MIN_PITCH: float = deg_to_rad(-60.0)
@export var MAX_PITCH: float = deg_to_rad(60.0)

@onready var anim_sprite: AnimatedSprite3D = $AnimatedSprite3D
# Предполагается, что узлы Camera3D находятся внутри Player
# Если у тебя камера называется по-другому, подправь путь (например, $Camera3D)
@onready var camera: Camera3D = $Camera3D

var is_dashing: bool = false
var dash_timer: float = 0.0
var dash_duration: float = 0.15

func _ready() -> void:
	# Захватываем мышь при старте игры
	Input.mouse_mode = Input.MOUSE_MODE_CAPTURED

func _unhandled_input(event: InputEvent) -> void:
	# 1. Поворот камеры и игрока мышью
	if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
		# Вращаем тело игрока по горизонтали (вправо/влево)
		rotate_y(-event.relative.x * MOUSE_SENSITIVITY)
		
		# Наклоняем только камеру по вертикали (вверх/вниз)
		if camera:
			camera.rotate_x(-event.relative.y * MOUSE_SENSITIVITY)
			# Ограничиваем угол наклона, чтобы камера не переворачивалась вверх ногами
			camera.rotation.x = clamp(camera.rotation.x, MIN_PITCH, MAX_PITCH)

	# 2. Нажатие Escape отпускает/захватывает мышь
	if event.is_action_pressed("ui_cancel"):
		if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
			Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
		else:
			Input.mouse_mode = Input.MOUSE_MODE_CAPTURED

func _physics_process(delta: float) -> void:
	# Гравитация
	if not is_on_floor():
		velocity.y -= GRAVITY * delta

	# Рывок на Shift
	if Input.is_key_pressed(KEY_SHIFT):
		if not is_dashing:
			is_dashing = true
			dash_timer = dash_duration

	if is_dashing:
		dash_timer -= delta
		if dash_timer <= 0:
			is_dashing = false

	# Движение WASD относительно взгляда (направления игрока)
	var input_dir := Vector2.ZERO
	if Input.is_key_pressed(KEY_W) or Input.is_action_pressed("ui_up"):
		input_dir.y -= 1.0
	if Input.is_key_pressed(KEY_S) or Input.is_action_pressed("ui_down"):
		input_dir.y += 1.0
	if Input.is_key_pressed(KEY_A) or Input.is_action_pressed("ui_left"):
		input_dir.x -= 1.0
	if Input.is_key_pressed(KEY_D) or Input.is_action_pressed("ui_right"):
		input_dir.x += 1.0

	input_dir = input_dir.normalized()

	# Переводим локальные направления WASD в 3D-пространство относительно ориентации игрока
	var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()

	var current_speed = DASH_SPEED if is_dashing else SPEED

	if direction != Vector3.ZERO:
		velocity.x = direction.x * current_speed
		velocity.z = direction.z * current_speed
	else:
		velocity.x = move_toward(velocity.x, 0, current_speed)
		velocity.z = move_toward(velocity.z, 0, current_speed)

	move_and_slide()
	
	_update_animation(input_dir)

func _update_animation(input_dir: Vector2) -> void:
	if not anim_sprite or not anim_sprite.sprite_frames:
		return
		
	if is_dashing:
		if anim_sprite.sprite_frames.has_animation("dash"):
			anim_sprite.play("dash")
	elif input_dir != Vector2.ZERO:
		if anim_sprite.sprite_frames.has_animation("run"):
			anim_sprite.play("run")
	else:
		if anim_sprite.sprite_frames.has_animation("idle"):
			anim_sprite.play("idle")