47 lines
1.5 KiB
GDScript
47 lines
1.5 KiB
GDScript
extends Node
|
|
|
|
# ScreenShakeManager - Camera-local shake that follows the player
|
|
|
|
var camera: Camera3D
|
|
var shake_intensity: float = 0.0
|
|
var shake_duration: float = 0.0
|
|
var shake_timer: float = 0.0
|
|
var shake_offset: Vector3 = Vector3.ZERO
|
|
|
|
# Shake presets
|
|
const SHAKE_TARGETED: Dictionary = {"intensity": 0.15, "duration": 0.4}
|
|
const SHAKE_GOAL_COMPLETE: Dictionary = {"intensity": 0.1, "duration": 0.3}
|
|
const SHAKE_LIGHT: Dictionary = {"intensity": 0.05, "duration": 0.2}
|
|
|
|
func initialize(p_camera: Camera3D):
|
|
camera = p_camera
|
|
|
|
func shake(intensity: float, duration: float) -> void:
|
|
"""Trigger a camera shake. Intensity in world units, duration in seconds."""
|
|
if intensity <= 0 or duration <= 0:
|
|
return
|
|
# Take the stronger shake if already active
|
|
if shake_timer > 0 and intensity <= shake_intensity:
|
|
return
|
|
shake_intensity = intensity
|
|
shake_duration = duration
|
|
shake_timer = duration
|
|
|
|
func _process(delta: float) -> void:
|
|
if not camera or not is_instance_valid(camera):
|
|
return
|
|
if shake_timer > 0:
|
|
shake_timer -= delta
|
|
var progress = shake_timer / shake_duration
|
|
# Fade out intensity as timer expires
|
|
var current_intensity = shake_intensity * progress
|
|
# Random offset within intensity range
|
|
shake_offset = Vector3(
|
|
randf_range(-current_intensity, current_intensity),
|
|
randf_range(-current_intensity, current_intensity) * 0.5,
|
|
randf_range(-current_intensity, current_intensity)
|
|
)
|
|
camera.position += shake_offset
|
|
else:
|
|
shake_offset = Vector3.ZERO
|