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