Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / camera / GameCamera.cs
  1. using System;
  2. using System.Collections.Generic;
  3. using Godot;
  4.  
  5. /// <summary>
  6. /// 游戏相机
  7. /// </summary>
  8. public partial class GameCamera : Camera2D
  9. {
  10. /// <summary>
  11. /// 当前场景的相机对象
  12. /// </summary>
  13. public static GameCamera Main { get; private set; }
  14.  
  15. /// <summary>
  16. /// 相机坐标更新完成事件
  17. /// </summary>
  18. public event Action<float> OnPositionUpdateEvent;
  19.  
  20. /// <summary>
  21. /// 恢复系数
  22. /// </summary>
  23. [Export]
  24. public float RecoveryCoefficient = 25f;
  25. /// <summary>
  26. /// 抖动开关
  27. /// </summary>
  28. public bool EnableShake { get; set; } = true;
  29.  
  30. /// <summary>
  31. /// 镜头跟随鼠标进度 (0 - 1)
  32. /// </summary>
  33. public float FollowsMouseAmount = 0.15f;
  34. /// <summary>
  35. /// 相机跟随目标
  36. /// </summary>
  37. private Role _followTarget;
  38. // 3.5
  39. //public Vector2 SubPixelPosition { get; private set; }
  40.  
  41. private long _index = 0;
  42. private Vector2 _processDistanceSquared = Vector2.Zero;
  43. private Vector2 _processDirection = Vector2.Zero;
  44. //抖动数据
  45. private readonly Dictionary<long, Vector2> _shakeMap = new Dictionary<long, Vector2>();
  46. private Vector2 _camPos;
  47. private Vector2 _shakeOffset = Vector2.Zero;
  48.  
  49. public GameCamera()
  50. {
  51. Main = this;
  52. }
  53. public override void _Ready()
  54. {
  55. _camPos = GlobalPosition;
  56. }
  57.  
  58. public override void _Process(double delta)
  59. {
  60. var newDelta = (float)delta;
  61. _Shake(newDelta);
  62. // 3.5 写法
  63. // var player = GameApplication.Instance.RoomManager.Player;
  64. // var viewportContainer = GameApplication.Instance.SubViewportContainer;
  65. // var camPos = player.GlobalPosition;
  66. // _camPos = _camPos.Lerp(camPos, Mathf.Min(6 * newDelta, 1)) + _shakeOffset;
  67. // SubPixelPosition = _camPos.Round() - _camPos;
  68. // (viewportContainer.Material as ShaderMaterial)?.SetShaderParameter("offset", SubPixelPosition);
  69. // GlobalPosition = _camPos.Round();
  70.  
  71.  
  72. var world = GameApplication.Instance.World;
  73. if (world != null && !world.Pause && _followTarget != null)
  74. {
  75. var mousePosition = InputManager.CursorPosition;
  76. var targetPosition = _followTarget.GlobalPosition;
  77. Vector2 targetPos;
  78. //if (targetPosition.DistanceSquaredTo(mousePosition) >= 39999.992F) // >= (60 / 0.3f) * (60 / 0.3f)
  79. if (targetPosition.DistanceSquaredTo(mousePosition) >= (60 / FollowsMouseAmount) * (60 / FollowsMouseAmount))
  80. {
  81. targetPos = targetPosition.MoveToward(mousePosition, 60);
  82. }
  83. else
  84. {
  85. //targetPos = targetPosition.Lerp(mousePosition, 0.3f); //这里的0.3就是上面的 (60 / 0.3f) * (60 / 0.3f) 中的 0.3
  86. targetPos = targetPosition.Lerp(mousePosition, FollowsMouseAmount);
  87. }
  88. _camPos = _camPos.Lerp(targetPos, 20 * newDelta);
  89. GlobalPosition = _camPos.Round();
  90.  
  91. Offset = _shakeOffset.Round();
  92. //_temp = _camPos - targetPosition;
  93.  
  94. //调用相机更新事件
  95. if (OnPositionUpdateEvent != null)
  96. {
  97. OnPositionUpdateEvent(newDelta);
  98. }
  99. }
  100. }
  101.  
  102. /// <summary>
  103. /// 设置相机跟随目标
  104. /// </summary>
  105. public void SetFollowTarget(Role target)
  106. {
  107. _followTarget = target;
  108. if (target != null)
  109. {
  110. _camPos = target.GlobalPosition;
  111. GlobalPosition = _camPos;
  112. }
  113. }
  114.  
  115. /// <summary>
  116. /// 获取相机跟随目标
  117. /// </summary>
  118. public Role GetFollowTarget()
  119. {
  120. return _followTarget;
  121. }
  122. /// <summary>
  123. /// 设置帧抖动, 结束后自动清零, 需要每一帧调用
  124. /// </summary>
  125. /// <param name="value">抖动的力度</param>
  126. public void Shake(Vector2 value)
  127. {
  128. if (value.LengthSquared() > _processDistanceSquared.LengthSquared())
  129. {
  130. _processDistanceSquared = value;
  131. }
  132. }
  133. /// <summary>
  134. /// 添加一个单方向上的抖动, 该帧结束后自动清零
  135. /// </summary>
  136. public void DirectionalShake(Vector2 value)
  137. {
  138. _processDirection += value;
  139. }
  140. /// <summary>
  141. /// 创建一个抖动, 并设置抖动时间
  142. /// </summary>
  143. public async void CreateShake(Vector2 value, float time)
  144. {
  145. if (time > 0)
  146. {
  147. value.X = Mathf.Abs(value.X);
  148. value.Y = Mathf.Abs(value.Y);
  149. var tempIndex = _index++;
  150. var sceneTreeTimer = GetTree().CreateTimer(time);
  151. _shakeMap[tempIndex] = value;
  152. await ToSignal(sceneTreeTimer, Timer.SignalName.Timeout);
  153. _shakeMap.Remove(tempIndex);
  154. }
  155. }
  156.  
  157. /// <summary>
  158. /// 播放玩家死亡特写镜头
  159. /// </summary>
  160. public void PlayPlayerDieFeatures()
  161. {
  162. }
  163.  
  164. //抖动调用
  165. private void _Shake(float delta)
  166. {
  167. if (EnableShake)
  168. {
  169. var distance = _CalculateDistanceSquared();
  170. distance = new Vector2(Mathf.Sqrt(distance.X), Mathf.Sqrt(distance.Y));
  171. _shakeOffset += _processDirection + new Vector2(
  172. (float)GD.RandRange(-distance.X, distance.X) - Offset.X,
  173. (float)GD.RandRange(-distance.Y, distance.Y) - Offset.Y
  174. );
  175. _processDistanceSquared = Vector2.Zero;
  176. _processDirection = _processDirection.Lerp(Vector2.Zero, RecoveryCoefficient * delta);
  177. }
  178. else
  179. {
  180. _shakeOffset = _shakeOffset.Lerp(Vector2.Zero, RecoveryCoefficient * delta);
  181. }
  182. }
  183.  
  184. //计算相机需要抖动的值
  185. private Vector2 _CalculateDistanceSquared()
  186. {
  187. var temp = Vector2.Zero;
  188. float length = 0;
  189. foreach (var keyValuePair in _shakeMap)
  190. {
  191. var tempLenght = keyValuePair.Value.LengthSquared();
  192. if (tempLenght > length)
  193. {
  194. length = tempLenght;
  195. temp = keyValuePair.Value;
  196. }
  197. }
  198. return _processDistanceSquared.LengthSquared() > length ? _processDistanceSquared : temp;
  199. }
  200. }