Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / camera / GameCamera.cs
@小李xl 小李xl on 5 Nov 2022 3 KB 解决武器旋转角度问题
  1. using System.Collections.Generic;
  2. using Godot;
  3.  
  4. /// <summary>
  5. /// 游戏相机
  6. /// </summary>
  7. public 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(float delta)
  41. {
  42. _Shake(delta);
  43. var player = GameApplication.Instance.Room.Player;
  44. var viewportContainer = GameApplication.Instance.ViewportContainer;
  45. var camPos = player.GlobalPosition;
  46. //var camPos = player.GlobalPosition.LinearInterpolate(mousePos, 0);
  47. //_camPos = camPos + _shakeOffset;
  48. _camPos = _camPos.LinearInterpolate(camPos, Mathf.Min(5 * delta, 1)) + _shakeOffset;
  49. SubPixelPosition = _camPos.Round() - _camPos;
  50. (viewportContainer.Material as ShaderMaterial)?.SetShaderParam("offset", SubPixelPosition);
  51. GlobalPosition = _camPos.Round();
  52. }
  53. /// <summary>
  54. /// 设置帧抖动, 结束后自动清零, 需要每一帧调用
  55. /// </summary>
  56. /// <param name="value">抖动的力度</param>
  57. public void ProcessShake(Vector2 value)
  58. {
  59. if (value.Length() > _processDistance.Length())
  60. {
  61. _processDistance = value;
  62. }
  63. }
  64.  
  65. public void ProcessDirectionalShake(Vector2 value)
  66. {
  67. _processDirection += value;
  68. }
  69.  
  70. /// <summary>
  71. /// 创建一个抖动, 并设置抖动时间
  72. /// </summary>
  73. /// <param name="value">抖动力度</param>
  74. /// <param name="time">抖动生效时间</param>
  75. public async void CreateShake(Vector2 value, float time)
  76. {
  77. if (time > 0)
  78. {
  79. long tempIndex = _index++;
  80. SceneTreeTimer sceneTreeTimer = GetTree().CreateTimer(time);
  81. _shakeMap[tempIndex] = value;
  82. await ToSignal(sceneTreeTimer, "timeout");
  83. _shakeMap.Remove(tempIndex);
  84. }
  85. }
  86.  
  87. //抖动调用
  88. private void _Shake(float delta)
  89. {
  90. if (Enable)
  91. {
  92. var distance = _CalculateDistance();
  93. _shakeOffset += _processDirection + new Vector2(
  94. (float)GD.RandRange(-distance.x, distance.x) - _shakeOffset.x,
  95. (float)GD.RandRange(-distance.y, distance.y) - _shakeOffset.y
  96. );
  97. _processDistance = Vector2.Zero;
  98. _processDirection = Vector2.Zero;
  99. }
  100. else
  101. {
  102. _shakeOffset = _shakeOffset.LinearInterpolate(Vector2.Zero, RecoveryCoefficient * delta);
  103. }
  104. }
  105.  
  106. //计算相机需要抖动的值
  107. private Vector2 _CalculateDistance()
  108. {
  109. Vector2 temp = Vector2.Zero;
  110. float length = 0;
  111. foreach (var item in _shakeMap)
  112. {
  113. var value = item.Value;
  114. float tempLenght = value.Length();
  115. if (tempLenght > length)
  116. {
  117. length = tempLenght;
  118. temp = value;
  119. }
  120. }
  121. return _processDistance.Length() > length ? _processDistance : temp;
  122. }
  123.  
  124. }