Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / camera / GameCamera.cs
  1. using System.Collections.Generic;
  2. using Godot;
  3.  
  4. /// <summary>
  5. /// 游戏相机
  6. /// </summary>
  7. public partial class GameCamera : Camera2D
  8. {
  9. /// <summary>
  10. /// 当前场景的相机对象
  11. /// </summary>
  12. public static GameCamera Main { get; private set; }
  13.  
  14. /// <summary>
  15. /// 恢复系数
  16. /// </summary>
  17. [Export]
  18. public float RecoveryCoefficient = 100f;
  19. /// <summary>
  20. /// 抖动开关
  21. /// </summary>
  22. public bool Enable { get; set; } = true;
  23. public Vector2 SubPixelPosition { get; private set; }
  24.  
  25. private long _index = 0;
  26. private Vector2 _processDistance = Vector2.Zero;
  27. private Vector2 _processDirection = Vector2.Zero;
  28. private readonly Dictionary<long, Vector2> _shakeMap = new Dictionary<long, Vector2>();
  29. private Vector2 _camPos;
  30. private Vector2 _shakeOffset = Vector2.Zero;
  31.  
  32. public override void _Ready()
  33. {
  34. Main = this;
  35. _camPos = GlobalPosition;
  36. }
  37.  
  38. //public override void _PhysicsProcess(float delta);
  39.  
  40. public override void _Process(double delta)
  41. {
  42. var newDelta = (float)delta;
  43. _Shake(newDelta);
  44. var player = GameApplication.Instance.RoomManager.Player;
  45. var viewportContainer = GameApplication.Instance.SubViewportContainer;
  46. var camPos = player.GlobalPosition;
  47. //var camPos = player.GlobalPosition.Lerp(mousePos, 0);
  48. //_camPos = camPos + _shakeOffset;
  49. _camPos = _camPos.Lerp(camPos, Mathf.Min(5 * newDelta, 1)) + _shakeOffset;
  50. SubPixelPosition = _camPos.Round() - _camPos;
  51. (viewportContainer.Material as ShaderMaterial)?.SetShaderParameter("offset", SubPixelPosition);
  52. GlobalPosition = _camPos.Round();
  53. }
  54. /// <summary>
  55. /// 设置帧抖动, 结束后自动清零, 需要每一帧调用
  56. /// </summary>
  57. /// <param name="value">抖动的力度</param>
  58. public void ProcessShake(Vector2 value)
  59. {
  60. if (value.Length() > _processDistance.Length())
  61. {
  62. _processDistance = value;
  63. }
  64. }
  65.  
  66. public void ProcessDirectionalShake(Vector2 value)
  67. {
  68. _processDirection += value;
  69. }
  70.  
  71. /// <summary>
  72. /// 创建一个抖动, 并设置抖动时间
  73. /// </summary>
  74. /// <param name="value">抖动力度</param>
  75. /// <param name="time">抖动生效时间</param>
  76. public async void CreateShake(Vector2 value, float time)
  77. {
  78. if (time > 0)
  79. {
  80. long tempIndex = _index++;
  81. SceneTreeTimer sceneTreeTimer = GetTree().CreateTimer(time);
  82. _shakeMap[tempIndex] = value;
  83. await ToSignal(sceneTreeTimer, "timeout");
  84. _shakeMap.Remove(tempIndex);
  85. }
  86. }
  87.  
  88. //抖动调用
  89. private void _Shake(float delta)
  90. {
  91. if (Enable)
  92. {
  93. var distance = _CalculateDistance();
  94. _shakeOffset += _processDirection + new Vector2(
  95. Utils.RandfRange(-distance.X, distance.X) - _shakeOffset.X,
  96. Utils.RandfRange(-distance.Y, distance.Y) - _shakeOffset.Y
  97. );
  98. _processDistance = Vector2.Zero;
  99. _processDirection = Vector2.Zero;
  100. }
  101. else
  102. {
  103. _shakeOffset = _shakeOffset.Lerp(Vector2.Zero, RecoveryCoefficient * delta);
  104. }
  105. }
  106.  
  107. //计算相机需要抖动的值
  108. private Vector2 _CalculateDistance()
  109. {
  110. Vector2 temp = Vector2.Zero;
  111. float length = 0;
  112. foreach (var item in _shakeMap)
  113. {
  114. var value = item.Value;
  115. float tempLenght = value.Length();
  116. if (tempLenght > length)
  117. {
  118. length = tempLenght;
  119. temp = value;
  120. }
  121. }
  122. return _processDistance.Length() > length ? _processDistance : temp;
  123. }
  124.  
  125. }