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