Добавил преследование
This commit is contained in:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user