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