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