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