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