Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / activity / components / MoveController.cs
@lijincheng lijincheng on 13 Feb 2023 6 KB 更改工程结构
  1.  
  2. using System.Collections.Generic;
  3. using Godot;
  4.  
  5. /// <summary>
  6. /// 移动控制器, 物体运动由力来控制, 不同方向的力速度最终会汇总
  7. /// </summary>
  8. public class MoveController : Component
  9. {
  10. private static long _index = 0;
  11.  
  12. /// <summary>
  13. /// 物体受到的外力的集合
  14. /// </summary>
  15. private readonly List<ExternalForce> _forceList = new List<ExternalForce>();
  16.  
  17. /// <summary>
  18. /// 这个速度就是物体当前物理帧移动的真实速率, 该速度由物理帧循环计算, 并不会马上更新
  19. /// 该速度就是 BasisVelocity + 外力总和
  20. /// </summary>
  21. public Vector2 Velocity => ActivityInstance.Velocity;
  22.  
  23. /// <summary>
  24. /// 物体的基础移动速率
  25. /// </summary>
  26. public Vector2 BasisVelocity
  27. {
  28. get => _basisVelocity;
  29. set => _basisVelocity = value;
  30. }
  31.  
  32. private Vector2 _basisVelocity = Vector2.Zero;
  33.  
  34. /// <summary>
  35. /// 获取所有外力对象
  36. /// </summary>
  37. public ExternalForce[] GetAllForce()
  38. {
  39. return _forceList.ToArray();
  40. }
  41.  
  42. /// <summary>
  43. /// 快速创建一个外力, 该外力为匿名外力, 当速率变为 0 时自动销毁
  44. /// </summary>
  45. /// <param name="velocity">外力速率</param>
  46. /// <param name="resistance">阻力大小</param>
  47. public ExternalForce AddConstantForce(Vector2 velocity, float resistance)
  48. {
  49. var force = AddConstantForce("_anonymity_" + _index++);
  50. force.Velocity = velocity;
  51. force.Resistance = resistance;
  52. return force;
  53. }
  54.  
  55. /// <summary>
  56. /// 根据名称添加一个外力, 并返回创建的外力的对象, 如果存在这个名称的外力, 移除之前的外力
  57. /// </summary>
  58. public ExternalForce AddConstantForce(string name)
  59. {
  60. var f = new ExternalForce(name);
  61. AddConstantForce(f);
  62. return f;
  63. }
  64.  
  65. /// <summary>
  66. /// 根据对象添加一个外力力, 如果存在这个名称的外力, 移除之前的外力
  67. /// </summary>
  68. public T AddConstantForce<T>(T force) where T : ExternalForce
  69. {
  70. RemoveForce(force.Name);
  71. _forceList.Add(force);
  72. return force;
  73. }
  74.  
  75. /// <summary>
  76. /// 根据名称移除一个外力
  77. /// </summary>
  78. public void RemoveForce(string name)
  79. {
  80. for (var i = 0; i < _forceList.Count; i++)
  81. {
  82. if (_forceList[i].Name == name)
  83. {
  84. _forceList.RemoveAt(i);
  85. return;
  86. }
  87. }
  88. }
  89.  
  90. /// <summary>
  91. /// 根据名称获取一个外力
  92. /// </summary>
  93. public ExternalForce GetForce(string name)
  94. {
  95. for (var i = 0; i < _forceList.Count; i++)
  96. {
  97. var externalForce = _forceList[i];
  98. if (externalForce.Name == name)
  99. {
  100. return externalForce;
  101. }
  102. }
  103.  
  104. return null;
  105. }
  106.  
  107. /// <summary>
  108. /// 检车是否有当前名称的外力对象
  109. /// </summary>
  110. public bool ContainsForce(string name)
  111. {
  112. for (var i = 0; i < _forceList.Count; i++)
  113. {
  114. var externalForce = _forceList[i];
  115. if (externalForce.Name == name)
  116. {
  117. return true;
  118. }
  119. }
  120.  
  121. return false;
  122. }
  123.  
  124. /// <summary>
  125. /// 根据对象移除一个外力
  126. /// </summary>
  127. public void RemoveForce(ExternalForce force)
  128. {
  129. RemoveForce(force.Name);
  130. }
  131.  
  132. /// <summary>
  133. /// 移除所有外力
  134. /// </summary>
  135. public void ClearForce()
  136. {
  137. _forceList.Clear();
  138. }
  139.  
  140. public override void PhysicsProcess(float delta)
  141. {
  142. if (_basisVelocity == Vector2.Zero && _forceList.Count == 0)
  143. {
  144. return;
  145. }
  146.  
  147. //先调用更新
  148. var externalForces = _forceList.ToArray();
  149. foreach (var fore in externalForces)
  150. {
  151. if (fore.Enable)
  152. fore.PhysicsProcess(delta);
  153. }
  154.  
  155. //外力总和
  156. var finallyEf = new Vector2();
  157. foreach (var fore in externalForces)
  158. {
  159. if (fore.Enable)
  160. finallyEf += fore.Velocity;
  161. }
  162.  
  163. //最终速率
  164. var finallyVelocity = _basisVelocity + finallyEf;
  165.  
  166. if (finallyVelocity != Vector2.Zero)
  167. {
  168. //计算移动
  169. ActivityInstance.Velocity = finallyVelocity;
  170. ActivityInstance.MoveAndSlide();
  171. var newVelocity = ActivityInstance.Velocity;
  172. if (newVelocity.X == 0f && _basisVelocity.X * finallyVelocity.X > 0)
  173. {
  174. _basisVelocity.X = 0;
  175. }
  176.  
  177. if (newVelocity.Y == 0f && _basisVelocity.Y * finallyVelocity.Y > 0)
  178. {
  179. _basisVelocity.Y = 0;
  180. }
  181.  
  182. //调整外力速率
  183. if (externalForces.Length > 0)
  184. {
  185. for (var i = 0; i < _forceList.Count; i++)
  186. {
  187. var force = _forceList[i];
  188. if (force.Enable)
  189. {
  190. var velocity = force.Velocity;
  191. force.Velocity = new Vector2(
  192. newVelocity.X == 0f && velocity.X * finallyVelocity.X > 0 ? 0 : velocity.X,
  193. newVelocity.Y == 0f && velocity.Y * finallyVelocity.Y > 0 ? 0 : velocity.Y
  194. );
  195.  
  196. if (force.Resistance != 0)
  197. {
  198. force.Velocity = force.Velocity.MoveToward(Vector2.Zero, force.Resistance * delta);
  199. }
  200.  
  201. if (force.AutoDestroy && force.Velocity == Vector2.Zero)
  202. {
  203. _forceList.RemoveAt(i--);
  204. }
  205. }
  206. }
  207. }
  208. }
  209. else
  210. {
  211. ActivityInstance.Velocity = Vector2.Zero;
  212. }
  213. }
  214.  
  215. public override void DebugDraw()
  216. {
  217. //绘制力大小和方向
  218. if (ActivityInstance is Bullet) //不绘制子弹的力
  219. {
  220. return;
  221. }
  222. var globalRotation = GlobalRotation;
  223. var flag = ActivityInstance.Scale.Y < 0;
  224. if (flag)
  225. {
  226. ActivityInstance.DrawLine(Vector2.Zero, (BasisVelocity * new Vector2(1, -1)).Rotated(-globalRotation),
  227. Colors.Yellow);
  228. }
  229. else
  230. {
  231. ActivityInstance.DrawLine(Vector2.Zero, BasisVelocity.Rotated(-globalRotation), Colors.Yellow);
  232. }
  233.  
  234. foreach (var force in _forceList)
  235. {
  236. if (flag)
  237. {
  238. ActivityInstance.DrawLine(Vector2.Zero, (force.Velocity * new Vector2(1, -1)).Rotated(globalRotation),
  239. Colors.YellowGreen);
  240. }
  241. else
  242. {
  243. ActivityInstance.DrawLine(Vector2.Zero, force.Velocity.Rotated(-globalRotation), Colors.YellowGreen);
  244. }
  245. }
  246. }
  247. }