Добавил преследование

This commit is contained in:
2026-10-27 14:57:54 +05:00
parent 6b34b8593f
commit 823d68ffd6
10 changed files with 242 additions and 18 deletions
+105
View File
@@ -98,6 +98,11 @@ const SLIDE_VIGNETTE = 0.45
const SPRINT_VIGNETTE = 0.2
const VIGNETTE_SPEED = 8.0
# --- Смерть (камень поймал) ---
const DEATH_TIME = 2.5 # Сколько лежим перед возрождением
const DEATH_CAMERA_HEIGHT = 0.3 # Камера падает почти на землю
const DEATH_ROLL = 75.0 # И заваливается набок (градусы)
const VIGNETTE_SHADER = """
shader_type canvas_item;
uniform float intensity : hint_range(0.0, 1.0) = 0.0;
@@ -162,8 +167,18 @@ var is_zooming: bool = false
# Виньетка
var vignette_material: ShaderMaterial = null
var vignette_rect: ColorRect = null
var vignette_value: float = 0.0
# Смерть
signal died
signal respawned
var is_dead: bool = false
var death_timer: float = 0.0
var spawn_transform: Transform3D
var death_overlay: ColorRect = null
var death_label: Label = null
# Коллайдер (опционально, ищется по имени CollisionShape3D)
var collision_shape: CollisionShape3D = null
var capsule: CapsuleShape3D = null
@@ -188,6 +203,8 @@ func _ready() -> void:
default_collision_y = collision_shape.position.y
_setup_vignette()
_setup_death_screen()
spawn_transform = global_transform
func _setup_vignette() -> void:
var layer := CanvasLayer.new()
@@ -198,6 +215,7 @@ func _setup_vignette() -> void:
rect.mouse_filter = Control.MOUSE_FILTER_IGNORE
layer.add_child(rect)
rect.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
vignette_rect = rect
var shader := Shader.new()
shader.code = VIGNETTE_SHADER
@@ -212,6 +230,9 @@ func _unhandled_input(event: InputEvent) -> void:
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
if is_dead:
return
if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
var zoom_factor := head.fov / base_fov
rotate_y(-event.relative.x * MOUSE_SENSITIVITY * zoom_factor)
@@ -246,6 +267,10 @@ func _get_input_dir() -> Vector2:
return input_dir.normalized()
func _physics_process(delta: float) -> void:
if is_dead:
_process_death(delta)
return
slide_cooldown_timer = maxf(slide_cooldown_timer - delta, 0.0)
dash_cooldown_timer = maxf(dash_cooldown_timer - delta, 0.0)
wallrun_cooldown_timer = maxf(wallrun_cooldown_timer - delta, 0.0)
@@ -812,9 +837,89 @@ func _update_camera(delta: float, input_dir: Vector2) -> void:
vignette_value = lerp(vignette_value, target_vignette, VIGNETTE_SPEED * delta)
if vignette_material:
vignette_material.set_shader_parameter("intensity", vignette_value)
# Невидимая виньетка не должна стоить заливки всего экрана (важно для веба)
vignette_rect.visible = vignette_value > 0.005
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
# --- СМЕРТЬ И ВОЗРОЖДЕНИЕ ---
func _setup_death_screen() -> void:
var layer := CanvasLayer.new()
layer.layer = 11
add_child(layer)
death_overlay = ColorRect.new()
death_overlay.mouse_filter = Control.MOUSE_FILTER_IGNORE
death_overlay.color = Color(0.6, 0.0, 0.0, 0.0)
death_overlay.visible = false
layer.add_child(death_overlay)
death_overlay.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
death_label = Label.new()
death_label.text = "ПОЙМАЛ!"
death_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
death_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
death_label.add_theme_font_size_override("font_size", 96)
death_label.add_theme_color_override("font_color", Color.WHITE)
death_label.add_theme_constant_override("outline_size", 12)
death_label.add_theme_color_override("font_outline_color", Color.BLACK)
death_label.visible = false
death_overlay.add_child(death_label)
death_label.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
func die() -> void:
if is_dead:
return
is_dead = true
death_timer = DEATH_TIME
if is_sliding:
_end_slide()
is_dashing = false
is_wallrunning = false
is_mantling = false
velocity = Vector3.ZERO
shake_strength = 0.25
death_label.visible = true
death_overlay.visible = true
died.emit()
func _process_death(delta: float) -> void:
death_timer -= delta
# Камера падает и заваливается набок, экран краснеет
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.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)
death_overlay.color.a = lerpf(death_overlay.color.a, 0.55, k)
# Падаем на землю, если умерли в воздухе
velocity.x = 0.0
velocity.z = 0.0
if not is_on_floor():
velocity += get_gravity() * delta
move_and_slide()
if death_timer <= 0.0:
_respawn()
func _respawn() -> void:
global_transform = spawn_transform
velocity = Vector3.ZERO
head.position = head_base_pos
head.rotation = Vector3.ZERO
current_roll = 0.0
head_offset_y = 0.0
land_offset = 0.0
step_offset = 0.0
death_overlay.color.a = 0.0
death_label.visible = false
death_overlay.visible = false
is_dead = false
respawned.emit()