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


extends CharacterBody3D

@export var speed = 5.0
@export var run_speed = 9.0
@export var crouch_speed = 2.5
@export var jump_velocity = 6.5

@export var mouse_sensitivity = 0.002

# Угол вертикального поворота камеры
var camera_angle = 0.0

# Высота камеры
@export var standing_camera_height = 1.3
@export var crouching_camera_height = 0.7

# Скорость перехода между стоянием и приседанием
@export var crouch_transition_speed = 8.0

@export var walk_bob_speed = 8.0
@export var walk_bob_amount = 0.04

@export var run_bob_speed = 13.0
@export var run_bob_amount = 0.07

var bob_time = 0.0

var is_runnig = false
var is_crouching = false

@onready var camera = $Camera3D
@onready var raycast = $Camera3D/RayCast3D

# Гравитация
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")


func _ready():
	# Захватываем мышь
	Input.mouse_mode = Input.MOUSE_MODE_CAPTURED


func _input(event):

	# Движение мыши
	if event is InputEventMouseMotion:
		if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:

			# Поворот персонажа влево / вправо
			rotate_y(-event.relative.x * mouse_sensitivity)

			# Поворот камеры вверх / вниз
			var change = -event.relative.y * mouse_sensitivity
			camera_angle += change

			# Ограничиваем вертикальный угол камеры
			camera_angle = clamp(camera_angle, -1.5, 1.5)

			# Применяем вращение камеры
			camera.rotation.x = camera_angle



func _physics_process(delta):

	if not is_on_floor():
		velocity.y -= gravity * delta

	if Input.is_action_just_pressed("прыж") and is_on_floor():
		velocity.y = jump_velocity

	var input_dir = Input.get_vector(
		"left",
		"right",
		"прямо",
		"назат"
	)

	var direction = (
		transform.basis * Vector3(input_dir.x, 0, input_dir.y)
	).normalized()


	is_crouching = Input.is_key_pressed(KEY_CTRL)

	var target_height = standing_camera_height

	if is_crouching:
		target_height = crouching_camera_height


	is_runnig = (
		Input.is_key_pressed(KEY_SHIFT)
		and not is_crouching
		and direction.length() > 0
	)

	var current_speed = speed

	if is_crouching:
		current_speed = crouch_speed

	elif is_runnig:
		current_speed = run_speed

	if direction.length() > 0:

		velocity.x = direction.x * current_speed
		velocity.z = direction.z * current_speed

	else:

		velocity.x = move_toward(
			velocity.x,
			0,
			speed * 0.5 * delta
		)

		velocity.z = move_toward(
			velocity.z,
			0,
			speed * 0.5 * delta
		)

	var horizontal_velocity = Vector2(
		velocity.x,
		velocity.z
	)

	var current_movement_speed = horizontal_velocity.length()


	if is_on_floor() and current_movement_speed > 0.1:


		if is_runnig:

			bob_time += delta * run_bob_speed

			var bob_x = cos(bob_time) * run_bob_amount
			var bob_y = abs(sin(bob_time)) * run_bob_amount

			camera.position.x = lerp(
				camera.position.x,
				bob_x,
				10.0 * delta
			)

			camera.position.y = lerp(
				camera.position.y,
				target_height + bob_y,
				10.0 * delta
			)


		else:

			bob_time += delta * walk_bob_speed

			var bob_x = cos(bob_time) * walk_bob_amount
			var bob_y = abs(sin(bob_time)) * walk_bob_amount

			camera.position.x = lerp(
				camera.position.x,
				bob_x,
				10.0 * delta
			)

			camera.position.y = lerp(
				camera.position.y,
				target_height + bob_y,
				10.0 * delta
			)


	else:

		camera.position.x = lerp(
			camera.position.x,
			0.0,
			10.0 * delta
		)

		camera.position.y = lerp(
			camera.position.y,
			target_height,
			10.0 * delta
		)


	if Input.is_action_just_pressed("interact"):

		if raycast.is_colliding():

			var object = raycast.get_collider()

			if object.has_method("interact"):
				object.interact()

	move_and_slide()