Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / activity / components / MoveController.cs
  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 void ScaleAllForce(float scale)
  38. {
  39. foreach (var externalForce in _forceList)
  40. {
  41. externalForce.Velocity *= scale;
  42. }
  43.  
  44. BasisVelocity *= scale;
  45. }
  46. /// <summary>
  47. /// 设置所有力对象, 包括基础速率
  48. /// </summary>
  49. public void SetAllForce(Vector2 value)
  50. {
  51. foreach (var externalForce in _forceList)
  52. {
  53. externalForce.Velocity = value;
  54. }
  55.  
  56. BasisVelocity = value;
  57. }
  58. /// <summary>
  59. /// 获取所有外力对象
  60. /// </summary>
  61. public ExternalForce[] GetAllForce()
  62. {
  63. return _forceList.ToArray();
  64. }
  65.  
  66. /// <summary>
  67. /// 快速创建一个外力, 该外力为匿名外力, 当速率变为 0 时自动销毁
  68. /// </summary>
  69. /// <param name="velocity">外力速率</param>
  70. /// <param name="resistance">阻力大小</param>
  71. public ExternalForce AddConstantForce(Vector2 velocity, float resistance)
  72. {
  73. var force = AddConstantForce("_anonymity_" + _index++);
  74. force.Velocity = velocity;
  75. force.Resistance = resistance;
  76. return force;
  77. }
  78.  
  79. /// <summary>
  80. /// 根据名称添加一个外力, 并返回创建的外力的对象, 如果存在这个名称的外力, 移除之前的外力, 当速率变为 0 时不会自动销毁
  81. /// </summary>
  82. public ExternalForce AddConstantForce(string name)
  83. {
  84. var f = new ExternalForce(name);
  85. f.AutoDestroy = false;
  86. AddConstantForce(f);
  87. return f;
  88. }
  89.  
  90. /// <summary>
  91. /// 根据对象添加一个外力力, 如果存在这个名称的外力, 移除之前的外力
  92. /// </summary>
  93. public T AddConstantForce<T>(T force) where T : ExternalForce
  94. {
  95. RemoveForce(force.Name);
  96. _forceList.Add(force);
  97. return force;
  98. }
  99.  
  100. /// <summary>
  101. /// 根据名称移除一个外力
  102. /// </summary>
  103. public void RemoveForce(string name)
  104. {
  105. for (var i = 0; i < _forceList.Count; i++)
  106. {
  107. if (_forceList[i].Name == name)
  108. {
  109. _forceList.RemoveAt(i);
  110. return;
  111. }
  112. }
  113. }
  114.  
  115. /// <summary>
  116. /// 根据名称获取一个外力
  117. /// </summary>
  118. public ExternalForce GetForce(string name)
  119. {
  120. for (var i = 0; i < _forceList.Count; i++)
  121. {
  122. var externalForce = _forceList[i];
  123. if (externalForce.Name == name)
  124. {
  125. return externalForce;
  126. }
  127. }
  128.  
  129. return null;
  130. }
  131.  
  132. /// <summary>
  133. /// 检车是否有当前名称的外力对象
  134. /// </summary>
  135. public bool ContainsForce(string name)
  136. {
  137. for (var i = 0; i < _forceList.Count; i++)
  138. {
  139. var externalForce = _forceList[i];
  140. if (externalForce.Name == name)
  141. {
  142. return true;
  143. }
  144. }
  145.  
  146. return false;
  147. }
  148.  
  149. /// <summary>
  150. /// 根据对象移除一个外力
  151. /// </summary>
  152. public void RemoveForce(ExternalForce force)
  153. {
  154. RemoveForce(force.Name);
  155. }
  156.  
  157. /// <summary>
  158. /// 移除所有外力
  159. /// </summary>
  160. public void ClearForce()
  161. {
  162. _forceList.Clear();
  163. }
  164.  
  165. public override void PhysicsProcess(float delta)
  166. {
  167. if (_basisVelocity == Vector2.Zero && _forceList.Count == 0)
  168. {
  169. return;
  170. }
  171.  
  172. //先调用更新
  173. var externalForces = _forceList.ToArray();
  174. for (var i = 0; i < externalForces.Length; i++)
  175. {
  176. var force = externalForces[i];
  177. if (force.Enable)
  178. {
  179. force.PhysicsProcess(delta);
  180. //自动销毁
  181. if (force.AutoDestroy && force.Velocity == Vector2.Zero)
  182. {
  183. _forceList.Remove(force);
  184. externalForces[i] = null;
  185. }
  186. }
  187. }
  188.  
  189. //外力总和
  190. var finallyEf = new Vector2();
  191. foreach (var force in externalForces)
  192. {
  193. if (force != null && force.Enable)
  194. finallyEf += force.Velocity;
  195. }
  196.  
  197. //最终速率
  198. var finallyVelocity = _basisVelocity + finallyEf;
  199.  
  200. if (finallyVelocity != Vector2.Zero)
  201. {
  202. //计算移动
  203. ActivityInstance.Velocity = finallyVelocity;
  204. ActivityInstance.MoveAndSlide();
  205. var newVelocity = ActivityInstance.Velocity;
  206. if (newVelocity.X == 0f && _basisVelocity.X * finallyVelocity.X > 0)
  207. {
  208. _basisVelocity.X = 0;
  209. }
  210.  
  211. if (newVelocity.Y == 0f && _basisVelocity.Y * finallyVelocity.Y > 0)
  212. {
  213. _basisVelocity.Y = 0;
  214. }
  215.  
  216. //调整外力速率
  217. for (var i = 0; i < _forceList.Count; i++)
  218. {
  219. var force = _forceList[i];
  220. if (force.Enable)
  221. {
  222. var velocity = force.Velocity;
  223. force.Velocity = new Vector2(
  224. newVelocity.X == 0f && velocity.X * finallyVelocity.X > 0 ? 0 : velocity.X,
  225. newVelocity.Y == 0f && velocity.Y * finallyVelocity.Y > 0 ? 0 : velocity.Y
  226. );
  227.  
  228. //力速度衰减
  229. if (force.Resistance != 0)
  230. {
  231. force.Velocity = force.Velocity.MoveToward(Vector2.Zero, force.Resistance * delta);
  232. }
  233.  
  234. //自动销毁
  235. if (force.AutoDestroy && force.Velocity == Vector2.Zero)
  236. {
  237. _forceList.RemoveAt(i--);
  238. }
  239. }
  240. }
  241. }
  242. else
  243. {
  244. ActivityInstance.Velocity = Vector2.Zero;
  245. }
  246. }
  247.  
  248. public override void DebugDraw()
  249. {
  250. //绘制力大小和方向
  251. if (ActivityInstance is Bullet) //不绘制子弹的力
  252. {
  253. return;
  254. }
  255. var globalRotation = GlobalRotation;
  256. var flag = ActivityInstance.Scale.Y < 0;
  257. if (flag)
  258. {
  259. ActivityInstance.DrawLine(Vector2.Zero, (BasisVelocity * new Vector2(1, -1)).Rotated(-globalRotation),
  260. Colors.Yellow);
  261. }
  262. else
  263. {
  264. ActivityInstance.DrawLine(Vector2.Zero, BasisVelocity.Rotated(-globalRotation), Colors.Yellow);
  265. }
  266.  
  267. foreach (var force in _forceList)
  268. {
  269. if (flag)
  270. {
  271. ActivityInstance.DrawLine(Vector2.Zero, (force.Velocity * new Vector2(1, -1)).Rotated(globalRotation),
  272. Colors.YellowGreen);
  273. }
  274. else
  275. {
  276. ActivityInstance.DrawLine(Vector2.Zero, force.Velocity.Rotated(-globalRotation), Colors.YellowGreen);
  277. }
  278. }
  279. }
  280. }