72 lines
2.0 KiB
C#
72 lines
2.0 KiB
C#
using Godot;
|
|
using MaxEffort.Code.Core;
|
|
|
|
namespace MaxEffort.Code.Systems;
|
|
|
|
[GlobalClass]
|
|
public partial class CameraShakeSystem : Node
|
|
{
|
|
[Export] private Camera2D _camera;
|
|
[Export] private float _decayRate = 0.8f; // How fast shaking stops
|
|
[Export] private float _maxOffset = 20.0f; // Max pixels to shake
|
|
[Export] private float _maxRoll = 0.1f; // Max rotation (radians)
|
|
|
|
private float _trauma = 0f; // Current shake intensity (0 to 1)
|
|
private float _currentFocus = 0f;
|
|
private RandomNumberGenerator _rng = new();
|
|
|
|
public override void _Ready()
|
|
{
|
|
EventBus.OnCameraTrauma += AddTrauma;
|
|
EventBus.OnFocusChanged += OnFocusChanged;
|
|
}
|
|
|
|
public override void _ExitTree()
|
|
{
|
|
EventBus.OnCameraTrauma -= AddTrauma;
|
|
EventBus.OnFocusChanged -= OnFocusChanged;
|
|
}
|
|
|
|
public override void _Process(double delta)
|
|
{
|
|
if (_camera == null) return;
|
|
|
|
if (_currentFocus > 0.75f)
|
|
{
|
|
AddTrauma(1.5f * (float)delta);
|
|
}
|
|
|
|
if (_trauma > 0)
|
|
{
|
|
_trauma -= _decayRate * (float)delta;
|
|
_trauma = Mathf.Max(0, _trauma);
|
|
|
|
var shake = _trauma * _trauma;
|
|
|
|
var offsetX = _maxOffset * shake * _rng.RandfRange(-1, 1);
|
|
var offsetY = _maxOffset * shake * _rng.RandfRange(-1, 1);
|
|
var rotation = _maxRoll * shake * _rng.RandfRange(-1, 1);
|
|
|
|
_camera.Offset = new Vector2(offsetX, offsetY);
|
|
_camera.Rotation = rotation;
|
|
}
|
|
else
|
|
{
|
|
if (_camera.Offset != Vector2.Zero)
|
|
{
|
|
_camera.Offset = _camera.Offset.Lerp(Vector2.Zero, (float)delta * 5f);
|
|
_camera.Rotation = Mathf.Lerp(_camera.Rotation, 0, (float)delta * 5f);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnFocusChanged(float focus)
|
|
{
|
|
_currentFocus = focus;
|
|
}
|
|
|
|
private void AddTrauma(float amount)
|
|
{
|
|
_trauma = Mathf.Clamp(_trauma + amount, 0f, 1f);
|
|
}
|
|
} |