Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / activity / ActivityObject.cs
@小李xl 小李xl on 16 Feb 2023 30 KB 地牢生成读取预设房间
  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 WaitForSeconds seconds) //等待秒数
  647. {
  648. item.WaitFor(seconds);
  649. }
  650. else if (next is WaitForFixedProcess process) //等待帧数
  651. {
  652. item.WaitFor(process);
  653. }
  654. }
  655. else
  656. {
  657. if (item.EnumeratorStack == null || item.EnumeratorStack.Count == 0)
  658. {
  659. StopCoroutine(item.Id);
  660. }
  661. else
  662. {
  663. item.Enumerator = item.EnumeratorStack.Pop();
  664. }
  665. }
  666. }
  667. }
  668. }
  669.  
  670. ProcessOver(newDelta);
  671. //调试绘制
  672. if (IsDebug)
  673. {
  674. QueueRedraw();
  675. }
  676. }
  677.  
  678. /// <summary>
  679. /// 每物理帧调用一次, 为了防止子类覆盖 _PhysicsProcess(), 给 _PhysicsProcess() 加上了 sealed, 子类需要帧循环函数请重写 PhysicsProcess() 函数
  680. /// </summary>
  681. public sealed override void _PhysicsProcess(double delta)
  682. {
  683. var newDelta = (float)delta;
  684. PhysicsProcess(newDelta);
  685. //更新组件
  686. if (_components.Count > 0)
  687. {
  688. var arr = _components.ToArray();
  689. for (int i = 0; i < arr.Length; i++)
  690. {
  691. if (IsDestroyed) return;
  692. var temp = arr[i].Value;
  693. if (temp != null && temp.ActivityInstance == this && temp.Enable)
  694. {
  695. if (!temp.IsReady)
  696. {
  697. temp.Ready();
  698. temp.IsReady = true;
  699. }
  700.  
  701. temp.PhysicsProcess(newDelta);
  702. }
  703. }
  704. }
  705.  
  706. PhysicsProcessOver(newDelta);
  707. }
  708.  
  709. /// <summary>
  710. /// 绘制函数, 子类不允许重写, 需要绘制函数请重写 DebugDraw()
  711. /// </summary>
  712. public sealed override void _Draw()
  713. {
  714. if (IsDebug)
  715. {
  716. DebugDraw();
  717. var arr = _components.ToArray();
  718. for (int i = 0; i < arr.Length; i++)
  719. {
  720. if (IsDestroyed) return;
  721. var temp = arr[i].Value;
  722. if (temp != null && temp.ActivityInstance == this && temp.Enable)
  723. {
  724. temp.DebugDraw();
  725. }
  726. }
  727. }
  728. }
  729.  
  730. /// <summary>
  731. /// 重新计算物体阴影的位置和旋转信息, 无论是否显示阴影
  732. /// </summary>
  733. public void CalcShadow()
  734. {
  735. //缩放
  736. ShadowSprite.Scale = AnimatedSprite.Scale;
  737. //阴影角度
  738. ShadowSprite.Rotation = 0;
  739. //阴影位置计算
  740. var pos = AnimatedSprite.GlobalPosition;
  741. if (_throwData != null && !_throwData.IsOver)
  742. {
  743. ShadowSprite.GlobalPosition = new Vector2(pos.X + ShadowOffset.X, pos.Y + ShadowOffset.Y + _throwData.Y);
  744. }
  745. else
  746. {
  747. ShadowSprite.GlobalPosition = pos + ShadowOffset;
  748. }
  749. }
  750. //计算位置
  751. private void CalcThrowAnimatedPosition()
  752. {
  753. if (Scale.Y < 0)
  754. {
  755. AnimatedSprite.GlobalPosition = GlobalPosition + new Vector2(0, -_throwData.Y) - _throwData.OriginSpritePosition.Rotated(Rotation) * Scale.Abs();
  756. }
  757. else
  758. {
  759. AnimatedSprite.GlobalPosition = GlobalPosition + new Vector2(0, -_throwData.Y) + _throwData.OriginSpritePosition.Rotated(Rotation);
  760. }
  761. }
  762.  
  763.  
  764. /// <summary>
  765. /// 销毁物体
  766. /// </summary>
  767. public void Destroy()
  768. {
  769. if (IsDestroyed)
  770. {
  771. return;
  772. }
  773.  
  774. IsDestroyed = true;
  775.  
  776. OnDestroy();
  777. QueueFree();
  778. var arr = _components.ToArray();
  779. for (int i = 0; i < arr.Length; i++)
  780. {
  781. arr[i].Value?.Destroy();
  782. }
  783. //临时处理, 4.0 有bug, 不能销毁模板实例, 不然关闭游戏会报错!!!
  784. _templateInstance.QueueFree();
  785. }
  786.  
  787. /// <summary>
  788. /// 延时销毁
  789. /// </summary>
  790. public void DelayDestroy()
  791. {
  792. CallDeferred(nameof(Destroy));
  793. }
  794.  
  795. /// <summary>
  796. /// 触发投抛动作
  797. /// </summary>
  798. private void Throw()
  799. {
  800. var parent = GetParent();
  801. //投抛时必须要加入 YSortLayer 节点下
  802. if (parent == null)
  803. {
  804. this.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  805. }
  806. else if (parent == GameApplication.Instance.RoomManager.NormalLayer)
  807. {
  808. parent.RemoveChild(this);
  809. this.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  810. }
  811.  
  812. GlobalPosition = _throwData.StartPosition;
  813.  
  814. CalcThrowAnimatedPosition();
  815. //显示阴影
  816. ShowShadowSprite();
  817. OnThrowStart();
  818. }
  819.  
  820. /// <summary>
  821. /// 设置投抛状态下的碰撞器
  822. /// </summary>
  823. private void SetThrowCollision()
  824. {
  825. if (_throwData != null && _throwData.UseOrigin)
  826. {
  827. _throwData.OriginShape = Collision.Shape;
  828. _throwData.OriginPosition = Collision.Position;
  829. _throwData.OriginRotation = Collision.Rotation;
  830. _throwData.OriginScale = Collision.Scale;
  831. _throwData.OriginZIndex = ZIndex;
  832. _throwData.OriginSpritePosition = AnimatedSprite.Position;
  833. _throwData.OriginCollisionEnable = Collision.Disabled;
  834. _throwData.OriginCollisionPosition = Collision.Position;
  835. _throwData.OriginCollisionRotation = Collision.Rotation;
  836. _throwData.OriginCollisionScale = Collision.Scale;
  837. _throwData.OriginCollisionMask = CollisionMask;
  838. _throwData.OriginCollisionLayer = CollisionLayer;
  839.  
  840. if (_throwData.RectangleShape == null)
  841. {
  842. _throwData.RectangleShape = new RectangleShape2D();
  843. }
  844.  
  845. Collision.Shape = _throwData.RectangleShape;
  846. Collision.Position = Vector2.Zero;
  847. Collision.Rotation = 0;
  848. Collision.Scale = Vector2.One;
  849. ZIndex = 0;
  850. Collision.Disabled = false;
  851. Collision.Position = Vector2.Zero;
  852. Collision.Rotation = 0;
  853. Collision.Scale = Vector2.One;
  854. CollisionMask = 1;
  855. CollisionLayer = 0;
  856. _throwData.UseOrigin = false;
  857. }
  858. }
  859.  
  860. /// <summary>
  861. /// 重置碰撞器
  862. /// </summary>
  863. private void RestoreCollision()
  864. {
  865. if (_throwData != null && !_throwData.UseOrigin)
  866. {
  867. Collision.Shape = _throwData.OriginShape;
  868. Collision.Position = _throwData.OriginPosition;
  869. Collision.Rotation = _throwData.OriginRotation;
  870. Collision.Scale = _throwData.OriginScale;
  871. ZIndex = _throwData.OriginZIndex;
  872. AnimatedSprite.Position = _throwData.OriginSpritePosition;
  873. Collision.Disabled = _throwData.OriginCollisionEnable;
  874. Collision.Position = _throwData.OriginCollisionPosition;
  875. Collision.Rotation = _throwData.OriginCollisionRotation;
  876. Collision.Scale = _throwData.OriginCollisionScale;
  877. CollisionMask = _throwData.OriginCollisionMask;
  878. CollisionLayer = _throwData.OriginCollisionLayer;
  879.  
  880. _throwData.UseOrigin = true;
  881. }
  882. }
  883.  
  884. /// <summary>
  885. /// 投抛结束
  886. /// </summary>
  887. private void ThrowOver()
  888. {
  889. //移除投抛的力
  890. MoveController.RemoveForce(_throwData.ThrowForce);
  891. GetParent().RemoveChild(this);
  892. this.AddToActivityRoot(_currLayer);
  893. RestoreCollision();
  894.  
  895. OnThrowOver();
  896. }
  897.  
  898. /// <summary>
  899. /// 设置标记, 用于在物体上记录自定义数据
  900. /// </summary>
  901. /// <param name="name">标记名称</param>
  902. /// <param name="v">存入值</param>
  903. public void SetSign(string name, object v)
  904. {
  905. if (_signMap == null)
  906. {
  907. _signMap = new Dictionary<string, object>();
  908. }
  909.  
  910. _signMap[name] = v;
  911. }
  912.  
  913. /// <summary>
  914. /// 返回是否存在指定名称的标记数据
  915. /// </summary>
  916. public bool HasSign(string name)
  917. {
  918. return _signMap == null ? false : _signMap.ContainsKey(name);
  919. }
  920.  
  921. /// <summary>
  922. /// 根据名称获取标记值
  923. /// </summary>
  924. public object GetSign(string name)
  925. {
  926. if (_signMap == null)
  927. {
  928. return null;
  929. }
  930.  
  931. _signMap.TryGetValue(name, out var value);
  932. return value;
  933. }
  934.  
  935. /// <summary>
  936. /// 根据名称获取标记值
  937. /// </summary>
  938. public T GetSign<T>(string name)
  939. {
  940. if (_signMap == null)
  941. {
  942. return default;
  943. }
  944.  
  945. _signMap.TryGetValue(name, out var value);
  946. if (value is T v)
  947. {
  948. return v;
  949. }
  950. return default;
  951. }
  952.  
  953. /// <summary>
  954. /// 根据名称删除标记
  955. /// </summary>
  956. public void RemoveSign(string name)
  957. {
  958. if (_signMap != null)
  959. {
  960. _signMap.Remove(name);
  961. }
  962. }
  963.  
  964. /// <summary>
  965. /// 播放受伤动画, 该动画不与 Animation 节点的动画冲突
  966. /// </summary>
  967. public void PlayHitAnimation()
  968. {
  969. _playHit = true;
  970. _playHitSchedule = 0;
  971. }
  972.  
  973. /// <summary>
  974. /// 开启一个协程, 返回协程 id, 协程是在普通帧执行的, 支持: 协程嵌套, WaitForSeconds, WaitForFixedProcess
  975. /// </summary>
  976. public long StartCoroutine(IEnumerable able)
  977. {
  978. if (_coroutineList == null)
  979. {
  980. _coroutineList = new List<CoroutineData>();
  981. }
  982.  
  983. var data = new CoroutineData(able.GetEnumerator());
  984. _coroutineList.Add(data);
  985. return data.Id;
  986. }
  987.  
  988. /// <summary>
  989. /// 根据协程 id 停止协程
  990. /// </summary>
  991. public void StopCoroutine(long coroutineId)
  992. {
  993. if (_coroutineList != null)
  994. {
  995. for (var i = 0; i < _coroutineList.Count; i++)
  996. {
  997. var item = _coroutineList[i];
  998. if (item.Id == coroutineId)
  999. {
  1000. _coroutineList.RemoveAt(i);
  1001. return;
  1002. }
  1003. }
  1004. }
  1005. }
  1006. /// <summary>
  1007. /// 停止所有协程
  1008. /// </summary>
  1009. public void StopAllCoroutine()
  1010. {
  1011. if (_coroutineList != null)
  1012. {
  1013. _coroutineList.Clear();
  1014. }
  1015. }
  1016. /// <summary>
  1017. /// 通过 ItemId 实例化 ActivityObject 对象
  1018. /// </summary>
  1019. public static T Create<T>(string itemId) where T : ActivityObject
  1020. {
  1021. return null;
  1022. }
  1023. }