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. force.MoveController = this;
  208. _forceList.Add(force);
  209. return force;
  210. }
  211.  
  212. /// <summary>
  213. /// 根据名称移除一个外力
  214. /// </summary>
  215. public void RemoveForce(string name)
  216. {
  217. for (var i = 0; i < _forceList.Count; i++)
  218. {
  219. if (_forceList[i].Name == name)
  220. {
  221. _forceList[i].MoveController = null;
  222. _forceList.RemoveAt(i);
  223. return;
  224. }
  225. }
  226. }
  227.  
  228. /// <summary>
  229. /// 根据名称获取一个外力
  230. /// </summary>
  231. public ExternalForce GetForce(string name)
  232. {
  233. for (var i = 0; i < _forceList.Count; i++)
  234. {
  235. var externalForce = _forceList[i];
  236. if (externalForce.Name == name)
  237. {
  238. return externalForce;
  239. }
  240. }
  241.  
  242. return null;
  243. }
  244.  
  245. /// <summary>
  246. /// 检车是否有当前名称的外力对象
  247. /// </summary>
  248. public bool ContainsForce(string name)
  249. {
  250. for (var i = 0; i < _forceList.Count; i++)
  251. {
  252. var externalForce = _forceList[i];
  253. if (externalForce.Name == name)
  254. {
  255. return true;
  256. }
  257. }
  258.  
  259. return false;
  260. }
  261.  
  262. /// <summary>
  263. /// 根据对象移除一个外力
  264. /// </summary>
  265. public void RemoveForce(ExternalForce force)
  266. {
  267. RemoveForce(force.Name);
  268. }
  269.  
  270. /// <summary>
  271. /// 移除所有外力
  272. /// </summary>
  273. public void ClearForce()
  274. {
  275. foreach (var force in _forceList)
  276. {
  277. force.MoveController = null;
  278. }
  279.  
  280. _forceList.Clear();
  281. }
  282.  
  283. public override void PhysicsProcess(float delta)
  284. {
  285. if (_basisVelocity == Vector2.Zero && _forceList.Count == 0)
  286. {
  287. Master.Velocity = Vector2.Zero;
  288. return;
  289. }
  290.  
  291. //外力总和
  292. var finallyEf = new Vector2();
  293. //旋转速率总和
  294. var rotationSpeed = 0f;
  295. //先调用更新
  296. if (_forceList.Count > 0)
  297. {
  298. var externalForces = _forceList.ToArray();
  299. for (var i = 0; i < externalForces.Length; i++)
  300. {
  301. var force = externalForces[i];
  302. if (force.Enable)
  303. {
  304. force.PhysicsProcess(delta);
  305. //自动销毁
  306. if (CheckAutoDestroy(force))
  307. {
  308. force.MoveController = null;
  309. _forceList.Remove(force);
  310. externalForces[i] = null;
  311. }
  312. else
  313. {
  314. finallyEf += force.Velocity;
  315. rotationSpeed += force.RotationSpeed;
  316. }
  317. }
  318. }
  319. }
  320.  
  321. //处理旋转
  322. if (rotationSpeed != 0)
  323. {
  324. Rotation += rotationSpeed * delta;
  325. }
  326. var friction = !Master.IsThrowing && Master.Altitude <= 0 ? Master.GetCurrentFriction() : 0;
  327. var rotationFriction = !Master.IsThrowing && Master.Altitude <= 0 ? Mathf.DegToRad(Master.GetCurrentRotationFriction()) : 0;
  328. //衰减旋转速率
  329. for (var i = 0; i < _forceList.Count; i++)
  330. {
  331. var force = _forceList[i];
  332. var num = (force.EnableResistanceInTheAir || !Master.IsThrowing) ? force.RotationResistance : 0;
  333. num += rotationFriction;
  334. if (num != 0)
  335. {
  336. force.RotationSpeed = Mathf.MoveToward(force.RotationSpeed, 0, num * delta);
  337. }
  338. }
  339.  
  340. //最终速率
  341. var finallyVelocity = _basisVelocity + finallyEf;
  342. //处理移动
  343. if (finallyVelocity != Vector2.Zero)
  344. {
  345. //计算移动
  346. Master.Velocity = finallyVelocity;
  347. Master.MoveAndSlide();
  348. //新速度
  349. var newVelocity = Master.Velocity;
  350. // if (newVelocity.X == 0f && _basisVelocity.X * finallyVelocity.X > 0)
  351. // {
  352. // _basisVelocity.X = 0;
  353. // }
  354. //
  355. // if (newVelocity.Y == 0f && _basisVelocity.Y * finallyVelocity.Y > 0)
  356. // {
  357. // _basisVelocity.Y = 0;
  358. // }
  359. //是否撞到物体
  360. KinematicCollision2D collision;
  361. _flag--;
  362. if (_flag <= 0 && (collision = Master.GetLastSlideCollision()) != null) //执行反弹操作
  363. {
  364. //调用移动碰撞函数
  365. Master.OnMoveCollision(collision);
  366. if (Master.IsDestroyed || (Master is IPoolItem poolItem && poolItem.IsRecycled))
  367. {
  368. return;
  369. }
  370. //2帧内不能再触发第二次碰撞检测
  371. _flag = 2;
  372. var no = collision.GetNormal().Rotated(Mathf.Pi * 0.5f);
  373. newVelocity = finallyEf.Reflect(no);
  374. var rotation = newVelocity.Angle();
  375. //调用反弹函数
  376. Master.OnBounce(rotation);
  377.  
  378. if (Enable && !Master.IsDestroyed)
  379. {
  380. if (Master.ActivityMaterial.RotationType == 1) //跟着反弹角度
  381. {
  382. Rotation = rotation;
  383. }
  384. else if (Master.ActivityMaterial.RotationType == 2) //跟着反弹角度, 带垂直角度
  385. {
  386. Rotation = rotation;
  387. AnimatedSprite.Rotation = new Vector2(newVelocity.X, newVelocity.Y - Master.VerticalSpeed).Angle() - rotation;
  388. }
  389. var length = _forceList.Count;
  390. if (length != 0)
  391. {
  392. var v = newVelocity / (length / Master.ActivityMaterial.BounceStrength);
  393. for (var i = 0; i < _forceList.Count; i++)
  394. {
  395. _forceList[i].Velocity = v;
  396. }
  397. }
  398. }
  399. }
  400. else //没有撞到物体
  401. {
  402. if (Master.ActivityMaterial.RotationType == 1) //跟着反弹角度
  403. {
  404. Rotation = newVelocity.Angle();
  405. }
  406. else if (Master.ActivityMaterial.RotationType == 2) //跟着反弹角度, 带垂直角度
  407. {
  408. var rotation = Rotation = newVelocity.Angle();
  409. AnimatedSprite.Rotation = new Vector2(newVelocity.X, newVelocity.Y - Master.VerticalSpeed).Angle() - rotation;
  410. }
  411. //调整外力速率
  412. for (var i = 0; i < _forceList.Count; i++)
  413. {
  414. var force = _forceList[i];
  415. if (force.Enable)
  416. {
  417. var velocity = force.Velocity;
  418. force.Velocity = new Vector2(
  419. newVelocity.X == 0f && velocity.X * finallyVelocity.X > 0 ? 0 : velocity.X,
  420. newVelocity.Y == 0f && velocity.Y * finallyVelocity.Y > 0 ? 0 : velocity.Y
  421. );
  422.  
  423. //力速度衰减
  424. var num = (force.EnableResistanceInTheAir || !Master.IsThrowing) ? force.VelocityResistance : 0;
  425. num += friction;
  426. if (num != 0)
  427. {
  428. force.Velocity = force.Velocity.MoveToward(Vector2.Zero, num * delta);
  429. }
  430. }
  431. }
  432. }
  433. }
  434. else
  435. {
  436. Master.Velocity = Vector2.Zero;
  437. }
  438. }
  439.  
  440. //检测是否达到自动销毁的条件
  441. private bool CheckAutoDestroy(ExternalForce force)
  442. {
  443. return force.AutoDestroy && force.Velocity == Vector2.Zero && force.RotationSpeed == 0;
  444. }
  445.  
  446. public override void DebugDraw()
  447. {
  448. //绘制力大小和方向
  449. if (Master is Bullet) //不绘制子弹的力
  450. {
  451. return;
  452. }
  453. var globalRotation = GlobalRotation;
  454. var flag = Master.Scale.Y < 0;
  455. if (flag)
  456. {
  457. Master.DrawLine(Vector2.Zero, (BasisVelocity * new Vector2(1, -1)).Rotated(-globalRotation),
  458. Colors.Yellow);
  459. }
  460. else
  461. {
  462. Master.DrawLine(Vector2.Zero, BasisVelocity.Rotated(-globalRotation), Colors.Yellow);
  463. }
  464.  
  465. foreach (var force in _forceList)
  466. {
  467. if (flag)
  468. {
  469. Master.DrawLine(Vector2.Zero, (force.Velocity * new Vector2(1, -1)).Rotated(globalRotation),
  470. Colors.YellowGreen);
  471. }
  472. else
  473. {
  474. Master.DrawLine(Vector2.Zero, force.Velocity.Rotated(-globalRotation), Colors.YellowGreen);
  475. }
  476. }
  477. }
  478. }