Двойной прыжок: камера делает сальто вперёд
- Камера вынесена в узел CameraPivot на уровне глаз; им крутим оборот за AIR_JUMP_FLIP_TIME (0,6 с, как у анимации air_jump), взгляд мышью не мешает - Рывок берёт направление без учёта сальто, смерть сбрасывает его - README: строка про сальто в таблице управления Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WxZo3ekR5m1af437Qzqwc1
This commit is contained in:
@@ -53,7 +53,7 @@ godot --path . # можно запустить несколько ок
|
||||
|---|---|
|
||||
| W A S D, стрелки | движение |
|
||||
| Shift | спринт |
|
||||
| Пробел | прыжок; держать у уступа в воздухе — подтянуться; у стены — прыжок от стены; в воздухе — двойной прыжок |
|
||||
| Пробел | прыжок; держать у уступа в воздухе — подтянуться; у стены — прыжок от стены; в воздухе — двойной прыжок (камера делает сальто, `AIR_JUMP_FLIP_TIME` в `player.gd`, 0 — выключить) |
|
||||
| C (держать) | **присед** (скорость 3,5, капсула вдвое ниже, пролезает под низкое) |
|
||||
| Shift + C на бегу | **подкат** |
|
||||
| Q | рывок |
|
||||
|
||||
+24
-2
@@ -20,6 +20,7 @@ const SLIDE_JUMP_BOOST = 1.15 # Бонус скорости при прыжк
|
||||
# --- Двойной прыжок ---
|
||||
const AIR_JUMPS = 1 # Сколько прыжков в воздухе (0 — отключить)
|
||||
const AIR_JUMP_VELOCITY = 5.5
|
||||
const AIR_JUMP_FLIP_TIME = 0.6 # Сальто камеры при двойном прыжке, сек (как у анимации air_jump; 0 — отключить)
|
||||
|
||||
# --- Рывок (клавиша Q) ---
|
||||
const DASH_SPEED = 20.0 # Не больше MAX_SPEED
|
||||
@@ -159,6 +160,8 @@ var mantle_target: Vector3 = Vector3.ZERO
|
||||
var mantle_dir: Vector3 = Vector3.ZERO
|
||||
|
||||
# Камера
|
||||
var flip_pivot: Node3D = null # Ось на уровне глаз: ею крутим сальто, не мешая взгляду мышью
|
||||
var flip_timer: float = 0.0
|
||||
var head_base_pos: Vector3 = Vector3.ZERO
|
||||
var head_offset_y: float = 0.0
|
||||
var land_offset: float = 0.0
|
||||
@@ -193,6 +196,12 @@ var default_collision_y: float = 0.0
|
||||
func _ready() -> void:
|
||||
add_to_group("local_player")
|
||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||
flip_pivot = Node3D.new()
|
||||
flip_pivot.name = "CameraPivot"
|
||||
flip_pivot.position = head.position
|
||||
add_child(flip_pivot)
|
||||
head.reparent(flip_pivot, false)
|
||||
head.position = Vector3.ZERO
|
||||
head_base_pos = head.position
|
||||
base_fov = head.fov
|
||||
|
||||
@@ -484,6 +493,7 @@ func _air_jump(direction: Vector3) -> void:
|
||||
velocity.y = AIR_JUMP_VELOCITY
|
||||
air_jumps_left -= 1
|
||||
jump_buffer_timer = 0.0
|
||||
flip_timer = AIR_JUMP_FLIP_TIME
|
||||
# Можно сменить направление полёта прямо в прыжке
|
||||
if direction != Vector3.ZERO:
|
||||
var h_speed: float = maxf(Vector2(velocity.x, velocity.z).length(), WALK_SPEED)
|
||||
@@ -497,7 +507,7 @@ func _try_dash() -> void:
|
||||
if is_dashing or is_mantling or dashes_left <= 0 or dash_cooldown_timer > 0.0:
|
||||
return
|
||||
|
||||
var look := -head.global_transform.basis.z
|
||||
var look := (global_transform.basis * Basis(Vector3.RIGHT, head.rotation.x)) * Vector3.FORWARD # без сальто камеры
|
||||
var dir: Vector3
|
||||
if is_on_floor():
|
||||
# На земле рвёмся по направлению ввода, а без ввода — вперёд
|
||||
@@ -794,7 +804,17 @@ func _can_stand() -> bool:
|
||||
|
||||
# --- КАМЕРА И ЭФФЕКТЫ ---
|
||||
|
||||
# Сальто вперёд: ось камеры делает полный оборот за AIR_JUMP_FLIP_TIME (плавно, с разгоном и торможением)
|
||||
func _update_flip(delta: float) -> void:
|
||||
flip_timer = maxf(flip_timer - delta, 0.0)
|
||||
if flip_timer <= 0.0:
|
||||
flip_pivot.rotation.x = 0.0
|
||||
return
|
||||
var u := 1.0 - flip_timer / AIR_JUMP_FLIP_TIME
|
||||
flip_pivot.rotation.x = -TAU * u * u * (3.0 - 2.0 * u)
|
||||
|
||||
func _update_camera(delta: float, input_dir: Vector2) -> void:
|
||||
_update_flip(delta)
|
||||
var h_speed := Vector2(velocity.x, velocity.z).length()
|
||||
var sprint_factor: float = clamp((h_speed - WALK_SPEED) / (SPRINT_SPEED - WALK_SPEED), 0.0, 1.0)
|
||||
|
||||
@@ -905,6 +925,8 @@ func die() -> void:
|
||||
return
|
||||
is_dead = true
|
||||
death_timer = DEATH_TIME
|
||||
flip_timer = 0.0
|
||||
flip_pivot.rotation.x = 0.0
|
||||
if is_sliding:
|
||||
_end_slide()
|
||||
if is_crouching:
|
||||
@@ -923,7 +945,7 @@ func _process_death(delta: float) -> void:
|
||||
|
||||
# Камера падает и заваливается набок, экран краснеет
|
||||
var k := 1.0 - exp(-6.0 * delta)
|
||||
head.position = head.position.lerp(Vector3(head_base_pos.x, DEATH_CAMERA_HEIGHT, head_base_pos.z), k)
|
||||
head.position = head.position.lerp(Vector3(head_base_pos.x, DEATH_CAMERA_HEIGHT - flip_pivot.position.y, head_base_pos.z), k)
|
||||
head.rotation.z = lerpf(head.rotation.z, deg_to_rad(DEATH_ROLL), k)
|
||||
head.fov = lerpf(head.fov, base_fov, k)
|
||||
shake_strength = lerpf(shake_strength, 0.0, 10.0 * delta)
|
||||
|
||||
Reference in New Issue
Block a user