using System.Collections.Generic; using Godot; public class MainCamera : Camera2D { /// <summary> /// 当前场景的相机对象 /// </summary> public static MainCamera Main { get; private set; } /// <summary> /// 恢复系数 /// </summary> [Export] public float RecoveryCoefficient = 100f; /// <summary> /// 抖动开关 /// </summary> public bool Enable { get; set; } = true; private long _index = 0; private Vector2 _prossesDistance = Vector2.Zero; private Vector2 _prossesDirectiona = Vector2.Zero; private readonly Dictionary<long, Vector2> _shakeMap = new Dictionary<long, Vector2>(); public override void _Ready() { Main = this; } public override void _PhysicsProcess(float delta) { _Shake(delta); } /// <summary> /// 设置帧抖动, 结束后自动清零, 需要每一帧调用 /// </summary> /// <param name="value">抖动的力度</param> public void ProssesShake(Vector2 value) { if (value.Length() > _prossesDistance.Length()) { _prossesDistance = value; } } public void ProssesDirectionalShake(Vector2 value) { _prossesDirectiona += value; } /// <summary> /// 创建一个抖动, 并设置抖动时间 /// </summary> /// <param name="value">抖动力度</param> /// <param name="time">抖动生效时间</param> public async void CreateShake(Vector2 value, float time) { if (time > 0) { long tempIndex = _index++; SceneTreeTimer sceneTreeTimer = GetTree().CreateTimer(time); _shakeMap[tempIndex] = value; await ToSignal(sceneTreeTimer, "timeout"); _shakeMap.Remove(tempIndex); } } //抖动调用 private void _Shake(float delta) { if (Enable) { var _distance = _CalculateDistance(); Offset += new Vector2( (float)GD.RandRange(-_distance.x, _distance.x) - Offset.x, (float)GD.RandRange(-_distance.y, _distance.y) - Offset.y ); Offset += _prossesDirectiona; _prossesDistance = Vector2.Zero; _prossesDirectiona = Vector2.Zero; } else { Offset = Offset.LinearInterpolate(Vector2.Zero, RecoveryCoefficient * delta); } } //计算相机需要抖动的值 private Vector2 _CalculateDistance() { Vector2 temp = Vector2.Zero; float length = 0; foreach (var item in _shakeMap) { var value = item.Value; float tempLenght = value.Length(); if (tempLenght > length) { length = tempLenght; temp = value; } } return _prossesDistance.Length() > length ? _prossesDistance : temp; } }