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 EnableShake { get; set; } = true;
  23.  
  24. /// <summary>
  25. /// 相机跟随目标
  26. /// </summary>
  27. private Role _followTarget;
  28. // 3.5
  29. //public Vector2 SubPixelPosition { get; private set; }
  30.  
  31. private long _index = 0;
  32. private Vector2 _processDistance = Vector2.Zero;
  33. private Vector2 _processDirection = Vector2.Zero;
  34. //抖动数据
  35. private readonly Dictionary<long, Vector2> _shakeMap = new Dictionary<long, Vector2>();
  36. private Vector2 _camPos;
  37. private Vector2 _shakeOffset = Vector2.Zero;
  38.  
  39. public override void _Ready()
  40. {
  41. Main = this;
  42. _camPos = GlobalPosition;
  43. }
  44.  
  45. public override void _Process(double delta)
  46. {
  47. var newDelta = (float)delta;
  48. _Shake(newDelta);
  49. // 3.5 写法
  50. // var player = GameApplication.Instance.RoomManager.Player;
  51. // var viewportContainer = GameApplication.Instance.SubViewportContainer;
  52. // var camPos = player.GlobalPosition;
  53. // _camPos = _camPos.Lerp(camPos, Mathf.Min(6 * newDelta, 1)) + _shakeOffset;
  54. // SubPixelPosition = _camPos.Round() - _camPos;
  55. // (viewportContainer.Material as ShaderMaterial)?.SetShaderParameter("offset", SubPixelPosition);
  56. // GlobalPosition = _camPos.Round();
  57.  
  58. if (_followTarget != null)
  59. {
  60. var mousePosition = InputManager.GetViewportMousePosition();
  61. var targetPosition = _followTarget.GlobalPosition;
  62. Vector2 targetPos;
  63. if (targetPosition.DistanceSquaredTo(mousePosition) >= (60 / 0.3f) * (60 / 0.3f))
  64. {
  65. targetPos = targetPosition.MoveToward(mousePosition, 60);
  66. }
  67. else
  68. {
  69. targetPos = targetPosition.Lerp(mousePosition, 0.3f);
  70. }
  71. _camPos = _camPos.Lerp(targetPos, Mathf.Min(6 * newDelta, 1)) + _shakeOffset;
  72. GlobalPosition = _camPos.Round();
  73. }
  74. }
  75.  
  76. /// <summary>
  77. /// 设置相机跟随目标
  78. /// </summary>
  79. public void SetFollowTarget(Role target)
  80. {
  81. _followTarget = target;
  82. GlobalPosition = target.GlobalPosition;
  83. }
  84.  
  85. /// <summary>
  86. /// 获取相机跟随目标
  87. /// </summary>
  88. public Role GetFollowTarget()
  89. {
  90. return _followTarget;
  91. }
  92. /// <summary>
  93. /// 设置帧抖动, 结束后自动清零, 需要每一帧调用
  94. /// </summary>
  95. /// <param name="value">抖动的力度</param>
  96. public void ProcessShake(Vector2 value)
  97. {
  98. if (value.Length() > _processDistance.Length())
  99. {
  100. _processDistance = value;
  101. }
  102. }
  103.  
  104. public void ProcessDirectionalShake(Vector2 value)
  105. {
  106. _processDirection += value;
  107. }
  108.  
  109. /// <summary>
  110. /// 创建一个抖动, 并设置抖动时间
  111. /// </summary>
  112. /// <param name="value">抖动力度</param>
  113. /// <param name="time">抖动生效时间</param>
  114. public async void CreateShake(Vector2 value, float time)
  115. {
  116. if (time > 0)
  117. {
  118. long tempIndex = _index++;
  119. SceneTreeTimer sceneTreeTimer = GetTree().CreateTimer(time);
  120. _shakeMap[tempIndex] = value;
  121. await ToSignal(sceneTreeTimer, "timeout");
  122. _shakeMap.Remove(tempIndex);
  123. }
  124. }
  125.  
  126. //抖动调用
  127. private void _Shake(float delta)
  128. {
  129. if (EnableShake)
  130. {
  131. var distance = _CalculateDistance();
  132. _shakeOffset += _processDirection + new Vector2(
  133. Utils.RandomRangeFloat(-distance.X, distance.X) - _shakeOffset.X,
  134. Utils.RandomRangeFloat(-distance.Y, distance.Y) - _shakeOffset.Y
  135. );
  136. _processDistance = Vector2.Zero;
  137. _processDirection = Vector2.Zero;
  138. }
  139. else
  140. {
  141. _shakeOffset = _shakeOffset.Lerp(Vector2.Zero, RecoveryCoefficient * delta);
  142. }
  143. }
  144.  
  145. //计算相机需要抖动的值
  146. private Vector2 _CalculateDistance()
  147. {
  148. Vector2 temp = Vector2.Zero;
  149. float length = 0;
  150. foreach (var item in _shakeMap)
  151. {
  152. var value = item.Value;
  153. float tempLenght = value.Length();
  154. if (tempLenght > length)
  155. {
  156. length = tempLenght;
  157. temp = value;
  158. }
  159. }
  160. return _processDistance.Length() > length ? _processDistance : temp;
  161. }
  162.  
  163. }