extends CharacterBody3D
@export_category("Movement Properties")
@export var SPEED : float = 12.0
@export var JUMP_VELOCITY : float = 14.0
@export var DASH_SPEED : float = 30.0
@export var DASH_DURATION : float = 0.2
@export_category("Camera Settings")
@export var MOUSE_SENSITIVITY : float = 0.003
# Получаем ссылки на узлы
@onready var camera_pivot: Node3D = $CameraPivot
@onready var sprite: Sprite3D = $Sprite3D
# Гравитация из настроек проекта
var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity") * 2.0
# Переменные состояния рывка
var is_dashing: bool = false
var dash_timer: float = 0.0
var dash_direction: Vector3 = Vector3.ZERO
func _ready() -> void:
# Захватываем курсор мыши
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
func _unhandled_input(event: InputEvent) -> void:
# Вращение камеры мышью
if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
camera_pivot.rotate_y(-event.relative.x * MOUSE_SENSITIVITY)
# Ограничиваем вертикальный угол камеры
var spring_arm = camera_pivot.get_node("SpringArm3D")
spring_arm.rotate_x(-event.relative.y * MOUSE_SENSITIVITY)
spring_arm.rotation.x = clamp(spring_arm.rotation.x, deg_to_rad(-60), deg_to_rad(30))
# Выход из режима захвата мыши по Esc
if event.is_action_pressed("ui_cancel"):
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
func _physics_process(delta: float) -> void:
# 1. Гравитация
if not is_on_floor():
velocity.y -= gravity * delta
# 2. Прыжок
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = JUMP_VELOCITY
# 3. Обработка Рывка (Dash)
if Input.is_action_just_pressed("dash") and not is_dashing:
start_dash()
if is_dashing:
dash_timer -= delta
velocity.x = dash_direction.x * DASH_SPEED
velocity.z = dash_direction.z * DASH_SPEED
if dash_timer <= 0:
is_dashing = false
else:
# 4. Обычное перемещение относительно направления камеры
var input_dir := Input.get_vector("move_left", "move_right", "move_forward", "move_back")
var direction := (camera_pivot.transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if direction:
velocity.x = direction.x * SPEED
velocity.z = direction.z * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
velocity.z = move_toward(velocity.z, 0, SPEED)
move_and_slide()
func start_dash() -> void:
is_dashing = true
dash_timer = DASH_DURATION
var input_dir := Input.get_vector("move_left", "move_right", "move_forward", "move_back")
# Если нажат вектор движения — рывок идет туда, иначе — вперед по камере
if input_dir != Vector2.ZERO:
dash_direction = (camera_pivot.transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
else:
dash_direction = -camera_pivot.transform.basis.z.normalized()