extends CharacterBody3D # Настройки скорости const WALK_SPEED = 5.0 const SPRINT_SPEED = 8.5 const JUMP_VELOCITY = 4.5 # Настройки чувствительности мыши @export var MOUSE_SENSITIVITY: float = 0.003 # --- Настройки тряски камеры (Head Bobbing) --- const BOB_FREQ = 2.4 # Частота покачивания const BOB_AMP = 0.08 # Амплитуда покачивания var bob_time: float = 0.0 # Ссылки на узлы @onready var head: Node3D = $Camera3D func _ready() -> void: Input.mouse_mode = Input.MOUSE_MODE_CAPTURED func _unhandled_input(event: InputEvent) -> void: if event.is_action_pressed("ui_cancel"): Input.mouse_mode = Input.MOUSE_MODE_VISIBLE if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT: Input.mouse_mode = Input.MOUSE_MODE_CAPTURED if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED: rotate_y(-event.relative.x * MOUSE_SENSITIVITY) head.rotate_x(-event.relative.y * MOUSE_SENSITIVITY) head.rotation.x = clamp(head.rotation.x, deg_to_rad(-80), deg_to_rad(80)) func _physics_process(delta: float) -> void: # 1. Гравитация if not is_on_floor(): velocity += get_gravity() * delta # 2. Прыжок на Пробел if Input.is_key_pressed(KEY_SPACE) and is_on_floor(): velocity.y = JUMP_VELOCITY # 3. Определение скорости (Спринт) var current_speed := WALK_SPEED if Input.is_key_pressed(KEY_SHIFT): current_speed = SPRINT_SPEED # 4. Управление WASD var input_dir := Vector2.ZERO if Input.is_key_pressed(KEY_D): input_dir.x += 1 if Input.is_key_pressed(KEY_A): input_dir.x -= 1 if Input.is_key_pressed(KEY_S): input_dir.y += 1 if Input.is_key_pressed(KEY_W): input_dir.y -= 1 input_dir = input_dir.normalized() # 5. Движение относительно взгляда персонажа var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized() if direction: 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) # 6. Эффект тряски / раскачивания камеры (Head Bobbing) bob_time += delta * velocity.length() * float(is_on_floor()) head.transform.origin = _head_bob(bob_time) move_and_slide() # Функция расчета позиционирования камеры при шагах func _head_bob(time: float) -> Vector3: var pos := Vector3.ZERO pos.y = sin(time * BOB_FREQ) * BOB_AMP pos.x = cos(time * BOB_FREQ / 2) * BOB_AMP return pos