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