Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / activity / ActivityObject.cs
  1.  
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using Godot;
  6.  
  7. /// <summary>
  8. /// 房间内活动物体基类, 所有物体都必须继承该类,
  9. /// ActivityObject 使用的时候代码和场景分离的设计模式, 所以创建时必须指定模板场景路径, 这样做的好处是一个模板场景可以用在多个代码类上, 同样一个代码类也可以指定不同的目模板场景,
  10. /// ActivityObject 子类实例化请不要直接使用 new, 而用该在类上标上 [RegisterActivity(id, prefabPath)],
  11. /// ActivityObject 类会自动扫描并注册物体, 然后使用而是使用 ActivityObject.Create(id) 来创建实例
  12. /// </summary>
  13. public abstract partial class ActivityObject : CharacterBody2D
  14. {
  15. /// <summary>
  16. /// 是否是调试模式
  17. /// </summary>
  18. public static bool IsDebug { get; set; }
  19.  
  20. /// <summary>
  21. /// 当前物体类型id, 用于区分是否是同一种物体, 如果不是通过 ActivityObject.Create() 函数创建出来的对象那么 ItemId 为 null
  22. /// </summary>
  23. public string ItemId { get; private set; }
  24.  
  25. /// <summary>
  26. /// 当前物体显示的精灵图像, 节点名称必须叫 "AnimatedSprite2D", 类型为 AnimatedSprite2D
  27. /// </summary>
  28. public AnimatedSprite2D AnimatedSprite { get; private set; }
  29.  
  30. /// <summary>
  31. /// 当前物体显示的阴影图像, 节点名称必须叫 "ShadowSprite", 类型为 Sprite2D
  32. /// </summary>
  33. public Sprite2D ShadowSprite { get; private set; }
  34.  
  35. /// <summary>
  36. /// 当前物体碰撞器节点, 节点名称必须叫 "Collision", 类型为 CollisionShape2D
  37. /// </summary>
  38. public CollisionShape2D Collision { get; private set; }
  39.  
  40. /// <summary>
  41. /// 是否调用过 Destroy() 函数
  42. /// </summary>
  43. public bool IsDestroyed { get; private set; }
  44.  
  45. /// <summary>
  46. /// 是否正在投抛过程中
  47. /// </summary>
  48. public bool IsThrowing => _throwData != null && !_throwData.IsOver;
  49.  
  50. /// <summary>
  51. /// 阴影偏移
  52. /// </summary>
  53. public Vector2 ShadowOffset { get; protected set; } = new Vector2(0, 2);
  54. /// <summary>
  55. /// 移动控制器
  56. /// </summary>
  57. public MoveController MoveController { get; private set; }
  58.  
  59. /// <summary>
  60. /// 物体移动基础速率
  61. /// </summary>
  62. public Vector2 BasisVelocity
  63. {
  64. get => MoveController.BasisVelocity;
  65. set => MoveController.BasisVelocity = value;
  66. }
  67.  
  68. /// <summary>
  69. /// 当前物体归属的区域, 如果为 null 代表不属于任何一个区域
  70. /// </summary>
  71. public AffiliationArea Affiliation
  72. {
  73. get => _affiliationArea;
  74. set
  75. {
  76. if (value != _affiliationArea)
  77. {
  78. _affiliationArea = value;
  79. OnAffiliationChange();
  80. }
  81. }
  82. }
  83.  
  84. //组件集合
  85. private List<KeyValuePair<Type, Component>> _components = new List<KeyValuePair<Type, Component>>();
  86. //是否初始化阴影
  87. private bool _initShadow;
  88. //上一帧动画名称
  89. private string _prevAnimation;
  90. //上一帧动画
  91. private int _prevAnimationFrame;
  92.  
  93. //播放 Hit 动画
  94. private bool _playHit;
  95. private float _playHitSchedule;
  96.  
  97. //混色shader材质
  98. private ShaderMaterial _blendShaderMaterial;
  99. //存储投抛该物体时所产生的数据
  100. private ActivityThrowData _throwData;
  101. //所在层级
  102. private RoomLayerEnum _currLayer;
  103. //标记字典
  104. private Dictionary<string, object> _signMap;
  105. //开启的协程
  106. private List<CoroutineData> _coroutineList;
  107. //模板实例
  108. private ActivityObjectTemplate _templateInstance;
  109. private AffiliationArea _affiliationArea;
  110. private static long _instanceIndex = 0;
  111.  
  112. //初始化节点
  113. private void _InitNode(string itemId, string scenePath)
  114. {
  115. //加载预制体
  116. var tempPrefab = ResourceManager.Load<PackedScene>(scenePath);
  117. if (tempPrefab == null)
  118. {
  119. throw new Exception("创建 ActivityObject 没有找到指定挂载的预制体: " + scenePath);
  120. }
  121.  
  122. ItemId = itemId;
  123. Name = GetType().Name + (_instanceIndex++);
  124. _templateInstance = tempPrefab.Instantiate<ActivityObjectTemplate>();
  125. //移动子节点
  126. var count = _templateInstance.GetChildCount();
  127. for (int i = 0; i < count; i++)
  128. {
  129. var body = _templateInstance.GetChild(0);
  130. _templateInstance.RemoveChild(body);
  131. AddChild(body);
  132. body.Owner = this;
  133. switch (body.Name)
  134. {
  135. case "AnimatedSprite":
  136. AnimatedSprite = (AnimatedSprite2D)body;
  137. _blendShaderMaterial = AnimatedSprite.Material as ShaderMaterial;
  138. break;
  139. case "ShadowSprite":
  140. ShadowSprite = (Sprite2D)body;
  141. ShadowSprite.Visible = false;
  142. break;
  143. case "Collision":
  144. Collision = (CollisionShape2D)body;
  145. break;
  146. }
  147. }
  148. ZIndex = _templateInstance.z_index;
  149. CollisionLayer = _templateInstance.collision_layer;
  150. CollisionMask = _templateInstance.collision_mask;
  151. Scale = _templateInstance.scale;
  152. Visible = _templateInstance.visible;
  153.  
  154. MotionMode = MotionModeEnum.Floating;
  155.  
  156. MoveController = AddComponent<MoveController>();
  157. //临时处理, 4.0 有bug, 不能销毁模板实例, 不然关闭游戏会报错!!!
  158. //_templateInstance.CallDeferred(Node.MethodName.QueueFree);
  159.  
  160. OnInit();
  161. }
  162.  
  163. /// <summary>
  164. /// 显示阴影
  165. /// </summary>
  166. public void ShowShadowSprite()
  167. {
  168. if (!_initShadow)
  169. {
  170. _initShadow = true;
  171. ShadowSprite.Material = ResourceManager.BlendMaterial;
  172. }
  173.  
  174. var anim = AnimatedSprite.Animation;
  175. var frame = AnimatedSprite.Frame;
  176. if (_prevAnimation != anim || _prevAnimationFrame != frame)
  177. {
  178. var frames = AnimatedSprite.SpriteFrames;
  179. if (frames.HasAnimation(anim))
  180. {
  181. //切换阴影动画
  182. ShadowSprite.Texture = frames.GetFrameTexture(anim, frame);
  183. }
  184. }
  185.  
  186. _prevAnimation = anim;
  187. _prevAnimationFrame = frame;
  188.  
  189. CalcShadow();
  190. ShadowSprite.Visible = true;
  191. }
  192.  
  193. /// <summary>
  194. /// 隐藏阴影
  195. /// </summary>
  196. public void HideShadowSprite()
  197. {
  198. ShadowSprite.Visible = false;
  199. }
  200.  
  201. /// <summary>
  202. /// 设置默认序列帧动画的第一帧
  203. /// </summary>
  204. public void SetDefaultTexture(Texture2D texture)
  205. {
  206. if (AnimatedSprite.SpriteFrames == null)
  207. {
  208. SpriteFrames spriteFrames = new SpriteFrames();
  209. AnimatedSprite.SpriteFrames = spriteFrames;
  210. spriteFrames.AddFrame("default", texture);
  211. }
  212. else
  213. {
  214. SpriteFrames spriteFrames = AnimatedSprite.SpriteFrames;
  215. spriteFrames.SetFrame("default", 0, texture);
  216. }
  217. AnimatedSprite.Play("default");
  218. }
  219.  
  220. /// <summary>
  221. /// 获取默认序列帧动画的第一帧
  222. /// </summary>
  223. public Texture2D GetDefaultTexture()
  224. {
  225. return AnimatedSprite.SpriteFrames.GetFrameTexture("default", 0);
  226. }
  227. /// <summary>
  228. /// 获取当前序列帧动画的 Texture2D
  229. /// </summary>
  230. public Texture2D GetCurrentTexture()
  231. {
  232. return AnimatedSprite.SpriteFrames.GetFrameTexture(AnimatedSprite.Name, AnimatedSprite.Frame);
  233. }
  234.  
  235. /// <summary>
  236. /// 物体初始化时调用
  237. /// </summary>
  238. public virtual void OnInit()
  239. {
  240. }
  241. /// <summary>
  242. /// 返回是否能与其他ActivityObject互动
  243. /// </summary>
  244. /// <param name="master">触发者</param>
  245. public virtual CheckInteractiveResult CheckInteractive(ActivityObject master)
  246. {
  247. return new CheckInteractiveResult(this);
  248. }
  249.  
  250. /// <summary>
  251. /// 与其它ActivityObject互动时调用, 如果要检测是否能互动请 CheckInteractive() 函数, 如果直接调用该函数那么属于强制互动行为, 例如子弹碰到物体
  252. /// </summary>
  253. /// <param name="master">触发者</param>
  254. public virtual void Interactive(ActivityObject master)
  255. {
  256. }
  257.  
  258. /// <summary>
  259. /// 开始投抛该物体时调用
  260. /// </summary>
  261. protected virtual void OnThrowStart()
  262. {
  263. }
  264. /// <summary>
  265. /// 投抛该物体达到最高点时调用
  266. /// </summary>
  267. protected virtual void OnThrowMaxHeight(float height)
  268. {
  269. }
  270.  
  271. /// <summary>
  272. /// 投抛状态下第一次接触地面时调用, 之后的回弹落地将不会调用该函数
  273. /// </summary>
  274. protected virtual void OnFirstFallToGround()
  275. {
  276. }
  277.  
  278. /// <summary>
  279. /// 投抛状态下每次接触地面时调用
  280. /// </summary>
  281. protected virtual void OnFallToGround()
  282. {
  283. }
  284.  
  285. /// <summary>
  286. /// 投抛结束时调用
  287. /// </summary>
  288. protected virtual void OnThrowOver()
  289. {
  290. }
  291.  
  292. /// <summary>
  293. /// 当前物体销毁时调用, 销毁物体请调用 Destroy() 函数
  294. /// </summary>
  295. protected virtual void OnDestroy()
  296. {
  297. }
  298.  
  299. /// <summary>
  300. /// 每帧调用一次, 物体的 Process() 会在组件的 Process() 之前调用
  301. /// </summary>
  302. protected virtual void Process(float delta)
  303. {
  304. }
  305. /// <summary>
  306. /// 每帧调用一次, ProcessOver() 会在组件的 Process() 之后调用
  307. /// </summary>
  308. protected virtual void ProcessOver(float delta)
  309. {
  310. }
  311. /// <summary>
  312. /// 每物理帧调用一次, 物体的 PhysicsProcess() 会在组件的 PhysicsProcess() 之前调用
  313. /// </summary>
  314. protected virtual void PhysicsProcess(float delta)
  315. {
  316. }
  317. /// <summary>
  318. /// 每物理帧调用一次, PhysicsProcessOver() 会在组件的 PhysicsProcess() 之后调用
  319. /// </summary>
  320. protected virtual void PhysicsProcessOver(float delta)
  321. {
  322. }
  323. /// <summary>
  324. /// 如果开启 debug, 则每帧调用该函数, 可用于绘制文字线段等
  325. /// </summary>
  326. protected virtual void DebugDraw()
  327. {
  328. }
  329.  
  330. /// <summary>
  331. /// 归属区域发生改变
  332. /// </summary>
  333. protected virtual void OnAffiliationChange()
  334. {
  335. }
  336.  
  337. /// <summary>
  338. /// 返回当物体 CollisionLayer 是否能与 mask 层碰撞
  339. /// </summary>
  340. public bool CollisionWithMask(uint mask)
  341. {
  342. return (CollisionLayer & mask) != 0;
  343. }
  344. /// <summary>
  345. /// 拾起一个 node 节点, 也就是将其从场景树中移除
  346. /// </summary>
  347. public void Pickup()
  348. {
  349. var parent = GetParent();
  350. if (parent != null)
  351. {
  352. if (IsThrowing)
  353. {
  354. StopThrow();
  355. }
  356.  
  357. parent.RemoveChild(this);
  358. }
  359. }
  360.  
  361. /// <summary>
  362. /// 将一个节点扔到地上
  363. /// <param name="layer">放入的层</param>
  364. /// <param name="showShadow">是否显示阴影</param>
  365. /// </summary>
  366. public virtual void PutDown(RoomLayerEnum layer, bool showShadow = true)
  367. {
  368. _currLayer = layer;
  369. var parent = GetParent();
  370. var root = GameApplication.Instance.RoomManager.GetRoomLayer(layer);
  371. if (parent != root)
  372. {
  373. if (parent != null)
  374. {
  375. parent.RemoveChild(this);
  376. }
  377.  
  378. this.AddToActivityRoot(layer);
  379. }
  380.  
  381. if (showShadow)
  382. {
  383. if (IsInsideTree())
  384. {
  385. ShowShadowSprite();
  386. }
  387. else
  388. {
  389. //注意需要延时调用
  390. CallDeferred(nameof(ShowShadowSprite));
  391. }
  392. }
  393. else
  394. {
  395. ShadowSprite.Visible = false;
  396. }
  397. }
  398.  
  399. /// <summary>
  400. /// 将一个节点扔到地上
  401. /// </summary>
  402. /// <param name="position">放置的位置</param>
  403. /// <param name="layer">放入的层</param>
  404. /// <param name="showShadow">是否显示阴影</param>
  405. public void PutDown(Vector2 position, RoomLayerEnum layer, bool showShadow = true)
  406. {
  407. PutDown(layer);
  408. Position = position;
  409. }
  410.  
  411. /// <summary>
  412. /// 将该节点投抛出去
  413. /// </summary>
  414. /// <param name="size">碰撞器大小</param>
  415. /// <param name="start">起始坐标 (全局)</param>
  416. /// <param name="startHeight">起始高度</param>
  417. /// <param name="direction">投抛角度 (0-360)</param>
  418. /// <param name="xSpeed">移动速度</param>
  419. /// <param name="ySpeed">下坠速度</param>
  420. /// <param name="rotate">旋转速度</param>
  421. /// <param name="bounce">落地时是否回弹</param>
  422. /// <param name="bounceStrength">落地回弹力度, 1为不消耗能量, 值越小回弹力度越小</param>
  423. /// <param name="bounceSpeed">落地回弹后的速度, 1为不消速度, 值越小回弹速度消耗越大</param>
  424. public void Throw(Vector2 size, Vector2 start, float startHeight, float direction, float xSpeed,
  425. float ySpeed, float rotate, bool bounce = false, float bounceStrength = 0.5f, float bounceSpeed = 0.8f)
  426. {
  427. if (_throwData == null)
  428. {
  429. _throwData = new ActivityThrowData();
  430. }
  431.  
  432. SetThrowCollision();
  433.  
  434. _throwData.IsOver = false;
  435. _throwData.Size = size;
  436. _throwData.StartPosition = _throwData.CurrPosition = start;
  437. _throwData.Direction = direction;
  438. _throwData.XSpeed = xSpeed;
  439. _throwData.YSpeed = ySpeed;
  440. _throwData.StartXSpeed = xSpeed;
  441. _throwData.StartYSpeed = ySpeed;
  442. _throwData.RotateSpeed = rotate;
  443. _throwData.ThrowForce = MoveController.AddConstantForce("ThrowForce");
  444. _throwData.ThrowForce.Velocity =
  445. new Vector2(_throwData.XSpeed, 0).Rotated(_throwData.Direction * Mathf.Pi / 180);
  446. _throwData.Y = startHeight;
  447. _throwData.Bounce = bounce;
  448. _throwData.BounceStrength = bounceStrength;
  449. _throwData.BounceSpeed = bounceSpeed;
  450.  
  451. _throwData.RectangleShape.Size = _throwData.Size * 0.5f;
  452.  
  453. Throw();
  454. }
  455.  
  456. /// <summary>
  457. /// 强制停止投抛运动
  458. /// </summary>
  459. public void StopThrow()
  460. {
  461. _throwData.IsOver = true;
  462. RestoreCollision();
  463. }
  464.  
  465. /// <summary>
  466. /// 往当前物体上挂载一个组件
  467. /// </summary>
  468. public T AddComponent<T>() where T : Component, new()
  469. {
  470. var component = new T();
  471. _components.Add(new KeyValuePair<Type, Component>(typeof(T), component));
  472. component.ActivityInstance = this;
  473. return component;
  474. }
  475.  
  476. /// <summary>
  477. /// 移除一个组件, 并且销毁
  478. /// </summary>
  479. /// <param name="component">组件对象</param>
  480. public void RemoveComponent(Component component)
  481. {
  482. for (int i = 0; i < _components.Count; i++)
  483. {
  484. if (_components[i].Value == component)
  485. {
  486. _components.RemoveAt(i);
  487. component.Destroy();
  488. return;
  489. }
  490. }
  491. }
  492.  
  493. /// <summary>
  494. /// 根据类型获取一个组件
  495. /// </summary>
  496. public Component GetComponent(Type type)
  497. {
  498. for (int i = 0; i < _components.Count; i++)
  499. {
  500. var temp = _components[i];
  501. if (temp.Key == type)
  502. {
  503. return temp.Value;
  504. }
  505. }
  506.  
  507. return null;
  508. }
  509.  
  510. /// <summary>
  511. /// 根据类型获取一个组件
  512. /// </summary>
  513. public T GetComponent<T>() where T : Component
  514. {
  515. var component = GetComponent(typeof(T));
  516. if (component == null) return null;
  517. return (T)component;
  518. }
  519. /// <summary>
  520. /// 每帧调用一次, 为了防止子类覆盖 _Process(), 给 _Process() 加上了 sealed, 子类需要帧循环函数请重写 Process() 函数
  521. /// </summary>
  522. public sealed override void _Process(double delta)
  523. {
  524. var newDelta = (float)delta;
  525. Process(newDelta);
  526. //更新组件
  527. if (_components.Count > 0)
  528. {
  529. var arr = _components.ToArray();
  530. for (int i = 0; i < arr.Length; i++)
  531. {
  532. if (IsDestroyed) return;
  533. var temp = arr[i].Value;
  534. if (temp != null && temp.ActivityInstance == this && temp.Enable)
  535. {
  536. if (!temp.IsReady)
  537. {
  538. temp.Ready();
  539. temp.IsReady = true;
  540. }
  541.  
  542. temp.Process(newDelta);
  543. }
  544. }
  545. }
  546.  
  547. //投抛计算
  548. if (_throwData != null && !_throwData.IsOver)
  549. {
  550. GlobalRotationDegrees = GlobalRotationDegrees + _throwData.RotateSpeed * newDelta;
  551. CalcThrowAnimatedPosition();
  552.  
  553. var ysp = _throwData.YSpeed;
  554.  
  555. _throwData.Y += _throwData.YSpeed * newDelta;
  556. _throwData.YSpeed -= GameConfig.G * newDelta;
  557.  
  558. //当高度大于16时, 显示在所有物体上
  559. if (_throwData.Y >= 16)
  560. {
  561. AnimatedSprite.ZIndex = 20;
  562. }
  563. else
  564. {
  565. AnimatedSprite.ZIndex = 0;
  566. }
  567. //达到最高点
  568. if (ysp * _throwData.YSpeed < 0)
  569. {
  570. OnThrowMaxHeight(_throwData.Y);
  571. }
  572.  
  573. //落地判断
  574. if (_throwData.Y <= 0)
  575. {
  576.  
  577. _throwData.IsOver = true;
  578.  
  579. //第一次接触地面
  580. if (_throwData.FirstOver)
  581. {
  582. _throwData.FirstOver = false;
  583. OnFirstFallToGround();
  584. }
  585.  
  586. //如果落地高度不够低, 再抛一次
  587. if (_throwData.StartYSpeed > 1 && _throwData.Bounce)
  588. {
  589. _throwData.StartPosition = Position;
  590. _throwData.Y = 0;
  591. _throwData.XSpeed = _throwData.StartXSpeed = _throwData.StartXSpeed * _throwData.BounceSpeed;
  592. _throwData.YSpeed = _throwData.StartYSpeed = _throwData.StartYSpeed * _throwData.BounceStrength;
  593. _throwData.RotateSpeed = _throwData.RotateSpeed * _throwData.BounceStrength;
  594. _throwData.ThrowForce.Velocity *= _throwData.BounceSpeed;
  595. _throwData.FirstOver = false;
  596. _throwData.IsOver = false;
  597.  
  598. OnFallToGround();
  599. }
  600. else //结束
  601. {
  602. OnFallToGround();
  603. ThrowOver();
  604. }
  605. }
  606. }
  607.  
  608. //阴影
  609. if (ShadowSprite.Visible)
  610. {
  611. //更新阴影贴图, 使其和动画一致
  612. var anim = AnimatedSprite.Animation;
  613. var frame = AnimatedSprite.Frame;
  614. if (_prevAnimation != anim || _prevAnimationFrame != frame)
  615. {
  616. //切换阴影动画
  617. ShadowSprite.Texture = AnimatedSprite.SpriteFrames.GetFrameTexture(anim, AnimatedSprite.Frame);
  618. }
  619.  
  620. _prevAnimation = anim;
  621. _prevAnimationFrame = frame;
  622.  
  623. //计算阴影
  624. CalcShadow();
  625. }
  626.  
  627. // Hit 动画
  628. if (_playHit && _blendShaderMaterial != null)
  629. {
  630. if (_playHitSchedule < 0.05f)
  631. {
  632. _blendShaderMaterial.SetShaderParameter("schedule", 1);
  633. }
  634. else if (_playHitSchedule < 0.15f)
  635. {
  636. _blendShaderMaterial.SetShaderParameter("schedule", Mathf.Lerp(1, 0, (_playHitSchedule - 0.05f) / 0.1f));
  637. }
  638. if (_playHitSchedule >= 0.15f)
  639. {
  640. _blendShaderMaterial.SetShaderParameter("schedule", 0);
  641. _playHitSchedule = 0;
  642. _playHit = false;
  643. }
  644. else
  645. {
  646. _playHitSchedule += newDelta;
  647. }
  648. }
  649. //协程更新
  650. if (_coroutineList != null)
  651. {
  652. var pairs = _coroutineList.ToArray();
  653. for (var i = 0; i < pairs.Length; i++)
  654. {
  655. var item = pairs[i];
  656. var canNext = true;
  657.  
  658. if (item.WaitType == CoroutineData.WaitTypeEnum.WaitForSeconds) //等待秒数
  659. {
  660. if (!item.WaitForSeconds.NextStep(newDelta))
  661. {
  662. canNext = false;
  663. }
  664. else
  665. {
  666. item.WaitType = CoroutineData.WaitTypeEnum.None;
  667. item.WaitForSeconds = null;
  668. }
  669. }
  670. else if (item.WaitType == CoroutineData.WaitTypeEnum.WaitForFixedProcess) //等待帧数
  671. {
  672. if (!item.WaitForFixedProcess.NextStep())
  673. {
  674. canNext = false;
  675. }
  676. else
  677. {
  678. item.WaitType = CoroutineData.WaitTypeEnum.None;
  679. item.WaitForFixedProcess = null;
  680. }
  681. }
  682.  
  683. if (canNext)
  684. {
  685. if (item.Enumerator.MoveNext()) //嵌套协程
  686. {
  687. var next = item.Enumerator.Current;
  688. if (next is IEnumerable enumerable)
  689. {
  690. if (item.EnumeratorStack == null)
  691. {
  692. item.EnumeratorStack = new Stack<IEnumerator>();
  693. }
  694.  
  695. item.EnumeratorStack.Push(item.Enumerator);
  696. item.Enumerator = enumerable.GetEnumerator();
  697. }
  698. else if (next is IEnumerator enumerator)
  699. {
  700. if (item.EnumeratorStack == null)
  701. {
  702. item.EnumeratorStack = new Stack<IEnumerator>();
  703. }
  704.  
  705. item.EnumeratorStack.Push(item.Enumerator);
  706. item.Enumerator = enumerator;
  707. }
  708. else if (next is WaitForSeconds seconds) //等待秒数
  709. {
  710. item.WaitFor(seconds);
  711. }
  712. else if (next is WaitForFixedProcess process) //等待帧数
  713. {
  714. item.WaitFor(process);
  715. }
  716. }
  717. else
  718. {
  719. if (item.EnumeratorStack == null || item.EnumeratorStack.Count == 0)
  720. {
  721. StopCoroutine(item.Id);
  722. }
  723. else
  724. {
  725. item.Enumerator = item.EnumeratorStack.Pop();
  726. }
  727. }
  728. }
  729. }
  730. }
  731.  
  732. ProcessOver(newDelta);
  733. //调试绘制
  734. if (IsDebug)
  735. {
  736. QueueRedraw();
  737. }
  738. }
  739.  
  740. /// <summary>
  741. /// 每物理帧调用一次, 为了防止子类覆盖 _PhysicsProcess(), 给 _PhysicsProcess() 加上了 sealed, 子类需要帧循环函数请重写 PhysicsProcess() 函数
  742. /// </summary>
  743. public sealed override void _PhysicsProcess(double delta)
  744. {
  745. var newDelta = (float)delta;
  746. PhysicsProcess(newDelta);
  747. //更新组件
  748. if (_components.Count > 0)
  749. {
  750. var arr = _components.ToArray();
  751. for (int i = 0; i < arr.Length; i++)
  752. {
  753. if (IsDestroyed) return;
  754. var temp = arr[i].Value;
  755. if (temp != null && temp.ActivityInstance == this && temp.Enable)
  756. {
  757. if (!temp.IsReady)
  758. {
  759. temp.Ready();
  760. temp.IsReady = true;
  761. }
  762.  
  763. temp.PhysicsProcess(newDelta);
  764. }
  765. }
  766. }
  767.  
  768. PhysicsProcessOver(newDelta);
  769. }
  770.  
  771. /// <summary>
  772. /// 绘制函数, 子类不允许重写, 需要绘制函数请重写 DebugDraw()
  773. /// </summary>
  774. public sealed override void _Draw()
  775. {
  776. if (IsDebug)
  777. {
  778. DebugDraw();
  779. var arr = _components.ToArray();
  780. for (int i = 0; i < arr.Length; i++)
  781. {
  782. if (IsDestroyed) return;
  783. var temp = arr[i].Value;
  784. if (temp != null && temp.ActivityInstance == this && temp.Enable)
  785. {
  786. temp.DebugDraw();
  787. }
  788. }
  789. }
  790. }
  791.  
  792. /// <summary>
  793. /// 重新计算物体阴影的位置和旋转信息, 无论是否显示阴影
  794. /// </summary>
  795. public void CalcShadow()
  796. {
  797. //缩放
  798. ShadowSprite.Scale = AnimatedSprite.Scale;
  799. //阴影角度
  800. ShadowSprite.Rotation = 0;
  801. //阴影位置计算
  802. var pos = AnimatedSprite.GlobalPosition;
  803. if (_throwData != null && !_throwData.IsOver)
  804. {
  805. ShadowSprite.GlobalPosition = new Vector2(pos.X + ShadowOffset.X, pos.Y + ShadowOffset.Y + _throwData.Y);
  806. }
  807. else
  808. {
  809. ShadowSprite.GlobalPosition = pos + ShadowOffset;
  810. }
  811. }
  812. //计算位置
  813. private void CalcThrowAnimatedPosition()
  814. {
  815. if (Scale.Y < 0)
  816. {
  817. AnimatedSprite.GlobalPosition = GlobalPosition + new Vector2(0, -_throwData.Y) - _throwData.OriginSpritePosition.Rotated(Rotation) * Scale.Abs();
  818. }
  819. else
  820. {
  821. AnimatedSprite.GlobalPosition = GlobalPosition + new Vector2(0, -_throwData.Y) + _throwData.OriginSpritePosition.Rotated(Rotation);
  822. }
  823. }
  824.  
  825.  
  826. /// <summary>
  827. /// 销毁物体
  828. /// </summary>
  829. public void Destroy()
  830. {
  831. if (IsDestroyed)
  832. {
  833. return;
  834. }
  835.  
  836. IsDestroyed = true;
  837. QueueFree();
  838. OnDestroy();
  839.  
  840. var arr = _components.ToArray();
  841. for (int i = 0; i < arr.Length; i++)
  842. {
  843. arr[i].Value?.Destroy();
  844. }
  845. if (Affiliation != null)
  846. {
  847. Affiliation.RemoveItem(this);
  848. }
  849. //临时处理, 4.0 有bug, 不能提前销毁模板实例, 不然关闭游戏会报错!!!
  850. _templateInstance.QueueFree();
  851. }
  852.  
  853. /// <summary>
  854. /// 延时销毁
  855. /// </summary>
  856. public void DelayDestroy()
  857. {
  858. CallDeferred(nameof(Destroy));
  859. }
  860.  
  861. /// <summary>
  862. /// 触发投抛动作
  863. /// </summary>
  864. private void Throw()
  865. {
  866. var parent = GetParent();
  867. //投抛时必须要加入 YSortLayer 节点下
  868. if (parent == null)
  869. {
  870. this.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  871. }
  872. else if (parent == GameApplication.Instance.RoomManager.NormalLayer)
  873. {
  874. parent.RemoveChild(this);
  875. this.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  876. }
  877.  
  878. GlobalPosition = _throwData.StartPosition;
  879.  
  880. CalcThrowAnimatedPosition();
  881. //显示阴影
  882. ShowShadowSprite();
  883. OnThrowStart();
  884. }
  885.  
  886. /// <summary>
  887. /// 设置投抛状态下的碰撞器
  888. /// </summary>
  889. private void SetThrowCollision()
  890. {
  891. if (_throwData != null && _throwData.UseOrigin)
  892. {
  893. _throwData.OriginShape = Collision.Shape;
  894. _throwData.OriginPosition = Collision.Position;
  895. _throwData.OriginRotation = Collision.Rotation;
  896. _throwData.OriginScale = Collision.Scale;
  897. _throwData.OriginZIndex = ZIndex;
  898. _throwData.OriginSpritePosition = AnimatedSprite.Position;
  899. _throwData.OriginCollisionEnable = Collision.Disabled;
  900. _throwData.OriginCollisionPosition = Collision.Position;
  901. _throwData.OriginCollisionRotation = Collision.Rotation;
  902. _throwData.OriginCollisionScale = Collision.Scale;
  903. _throwData.OriginCollisionMask = CollisionMask;
  904. _throwData.OriginCollisionLayer = CollisionLayer;
  905.  
  906. if (_throwData.RectangleShape == null)
  907. {
  908. _throwData.RectangleShape = new RectangleShape2D();
  909. }
  910.  
  911. Collision.Shape = _throwData.RectangleShape;
  912. Collision.Position = Vector2.Zero;
  913. Collision.Rotation = 0;
  914. Collision.Scale = Vector2.One;
  915. ZIndex = 0;
  916. Collision.Disabled = false;
  917. Collision.Position = Vector2.Zero;
  918. Collision.Rotation = 0;
  919. Collision.Scale = Vector2.One;
  920. CollisionMask = 1;
  921. CollisionLayer = 0;
  922. _throwData.UseOrigin = false;
  923. }
  924. }
  925.  
  926. /// <summary>
  927. /// 重置碰撞器
  928. /// </summary>
  929. private void RestoreCollision()
  930. {
  931. if (_throwData != null && !_throwData.UseOrigin)
  932. {
  933. Collision.Shape = _throwData.OriginShape;
  934. Collision.Position = _throwData.OriginPosition;
  935. Collision.Rotation = _throwData.OriginRotation;
  936. Collision.Scale = _throwData.OriginScale;
  937. ZIndex = _throwData.OriginZIndex;
  938. AnimatedSprite.Position = _throwData.OriginSpritePosition;
  939. Collision.Disabled = _throwData.OriginCollisionEnable;
  940. Collision.Position = _throwData.OriginCollisionPosition;
  941. Collision.Rotation = _throwData.OriginCollisionRotation;
  942. Collision.Scale = _throwData.OriginCollisionScale;
  943. CollisionMask = _throwData.OriginCollisionMask;
  944. CollisionLayer = _throwData.OriginCollisionLayer;
  945.  
  946. _throwData.UseOrigin = true;
  947. }
  948. }
  949.  
  950. /// <summary>
  951. /// 投抛结束
  952. /// </summary>
  953. private void ThrowOver()
  954. {
  955. //移除投抛的力
  956. MoveController.RemoveForce(_throwData.ThrowForce);
  957. GetParent().RemoveChild(this);
  958. this.AddToActivityRoot(_currLayer);
  959. RestoreCollision();
  960.  
  961. OnThrowOver();
  962. }
  963.  
  964. /// <summary>
  965. /// 设置标记, 用于在物体上记录自定义数据
  966. /// </summary>
  967. /// <param name="name">标记名称</param>
  968. /// <param name="v">存入值</param>
  969. public void SetSign(string name, object v)
  970. {
  971. if (_signMap == null)
  972. {
  973. _signMap = new Dictionary<string, object>();
  974. }
  975.  
  976. _signMap[name] = v;
  977. }
  978.  
  979. /// <summary>
  980. /// 返回是否存在指定名称的标记数据
  981. /// </summary>
  982. public bool HasSign(string name)
  983. {
  984. return _signMap == null ? false : _signMap.ContainsKey(name);
  985. }
  986.  
  987. /// <summary>
  988. /// 根据名称获取标记值
  989. /// </summary>
  990. public object GetSign(string name)
  991. {
  992. if (_signMap == null)
  993. {
  994. return null;
  995. }
  996.  
  997. _signMap.TryGetValue(name, out var value);
  998. return value;
  999. }
  1000.  
  1001. /// <summary>
  1002. /// 根据名称获取标记值
  1003. /// </summary>
  1004. public T GetSign<T>(string name)
  1005. {
  1006. if (_signMap == null)
  1007. {
  1008. return default;
  1009. }
  1010.  
  1011. _signMap.TryGetValue(name, out var value);
  1012. if (value is T v)
  1013. {
  1014. return v;
  1015. }
  1016. return default;
  1017. }
  1018.  
  1019. /// <summary>
  1020. /// 根据名称删除标记
  1021. /// </summary>
  1022. public void RemoveSign(string name)
  1023. {
  1024. if (_signMap != null)
  1025. {
  1026. _signMap.Remove(name);
  1027. }
  1028. }
  1029.  
  1030. /// <summary>
  1031. /// 播放受伤动画, 该动画不与 Animation 节点的动画冲突
  1032. /// </summary>
  1033. public void PlayHitAnimation()
  1034. {
  1035. _playHit = true;
  1036. _playHitSchedule = 0;
  1037. }
  1038.  
  1039. /// <summary>
  1040. /// 开启一个协程, 返回协程 id, 协程是在普通帧执行的, 支持: 协程嵌套, WaitForSeconds, WaitForFixedProcess
  1041. /// </summary>
  1042. public long StartCoroutine(IEnumerator able)
  1043. {
  1044. if (_coroutineList == null)
  1045. {
  1046. _coroutineList = new List<CoroutineData>();
  1047. }
  1048.  
  1049. var data = new CoroutineData(able);
  1050. _coroutineList.Add(data);
  1051. return data.Id;
  1052. }
  1053. /// <summary>
  1054. /// 开启一个协程, 返回协程 id, 协程是在普通帧执行的, 支持: 协程嵌套, WaitForSeconds, WaitForFixedProcess
  1055. /// </summary>
  1056. public long StartCoroutine(IEnumerable able)
  1057. {
  1058. return StartCoroutine(able.GetEnumerator());
  1059. }
  1060.  
  1061. /// <summary>
  1062. /// 根据协程 id 停止协程
  1063. /// </summary>
  1064. public void StopCoroutine(long coroutineId)
  1065. {
  1066. if (_coroutineList != null)
  1067. {
  1068. for (var i = 0; i < _coroutineList.Count; i++)
  1069. {
  1070. var item = _coroutineList[i];
  1071. if (item.Id == coroutineId)
  1072. {
  1073. _coroutineList.RemoveAt(i);
  1074. return;
  1075. }
  1076. }
  1077. }
  1078. }
  1079. /// <summary>
  1080. /// 停止所有协程
  1081. /// </summary>
  1082. public void StopAllCoroutine()
  1083. {
  1084. if (_coroutineList != null)
  1085. {
  1086. _coroutineList.Clear();
  1087. }
  1088. }
  1089. }