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 Config;
  6. using Godot;
  7.  
  8. /// <summary>
  9. /// 房间内活动物体基类, 所有物体都必须继承该类,<br/>
  10. /// ActivityObject 使用的时候代码和场景分离的设计模式, 所以创建时必须指定模板场景路径, 这样做的好处是一个模板场景可以用在多个代码类上, 同样一个代码类也可以指定不同的目模板场景, <br/>
  11. /// ActivityObject 子类实例化请不要直接使用 new, 而用该在类上标上 [Tool], 并在 ActivityObject.xlsx 配置文件中注册物体, 导出配置表后使用 ActivityObject.Create(id) 来创建实例.<br/>
  12. /// </summary>
  13. public abstract partial class ActivityObject : CharacterBody2D, IDestroy
  14. {
  15. /// <summary>
  16. /// 是否是调试模式
  17. /// </summary>
  18. public static bool IsDebug { get; set; }
  19.  
  20. /// <summary>
  21. /// 当前物体对应的配置数据, 如果不是通过 ActivityObject.Create() 函数创建出来的对象那么 ItemConfig 为 null
  22. /// </summary>
  23. public ExcelConfig.ActivityObject ItemConfig { get; private set; }
  24.  
  25. /// <summary>
  26. /// 是否是静态物体, 如果为true, 则会禁用移动处理
  27. /// </summary>
  28. [Export]
  29. public bool IsStatic { get; set; }
  30.  
  31. /// <summary>
  32. /// 当前物体显示的阴影图像, 节点名称必须叫 "ShadowSprite", 类型为 Sprite2D
  33. /// </summary>
  34. [Export, ExportFillNode]
  35. public Sprite2D ShadowSprite { get; set; }
  36. /// <summary>
  37. /// 当前物体显示的精灵图像, 节点名称必须叫 "AnimatedSprite2D", 类型为 AnimatedSprite2D
  38. /// </summary>
  39. [Export, ExportFillNode]
  40. public AnimatedSprite2D AnimatedSprite { get; set; }
  41.  
  42. /// <summary>
  43. /// 当前物体碰撞器节点, 节点名称必须叫 "Collision", 类型为 CollisionShape2D
  44. /// </summary>
  45. [Export, ExportFillNode]
  46. public CollisionShape2D Collision { get; set; }
  47.  
  48. /// <summary>
  49. /// 是否调用过 Destroy() 函数
  50. /// </summary>
  51. public bool IsDestroyed { get; private set; }
  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; private set; }
  60.  
  61. /// <summary>
  62. /// 物体移动基础速率
  63. /// </summary>
  64. public Vector2 BasisVelocity
  65. {
  66. get
  67. {
  68. if (MoveController != null)
  69. {
  70. return MoveController.BasisVelocity;
  71. }
  72.  
  73. return Vector2.Zero;
  74. }
  75. set
  76. {
  77. if (MoveController != null)
  78. {
  79. MoveController.BasisVelocity = value;
  80. }
  81. }
  82. }
  83.  
  84. /// <summary>
  85. /// 当前物体归属的区域, 如果为 null 代表不属于任何一个区域
  86. /// </summary>
  87. public AffiliationArea AffiliationArea
  88. {
  89. get => _affiliationArea;
  90. set
  91. {
  92. if (value != _affiliationArea)
  93. {
  94. _affiliationArea = value;
  95. if (!IsDestroyed)
  96. {
  97. OnAffiliationChange();
  98. }
  99. }
  100. }
  101. }
  102.  
  103. /// <summary>
  104. /// 是否正在投抛过程中
  105. /// </summary>
  106. public bool IsThrowing => _throwForce != null && !_isFallOver;
  107.  
  108. /// <summary>
  109. /// 当前物体的海拔高度, 如果大于0, 则会做自由落体运动, 也就是执行投抛代码
  110. /// </summary>
  111. public float Altitude
  112. {
  113. get => _altitude;
  114. set
  115. {
  116. _altitude = value;
  117. _hasResilienceVerticalSpeed = false;
  118. }
  119. }
  120.  
  121. private float _altitude = 0;
  122.  
  123. /// <summary>
  124. /// 物体纵轴移动速度, 如果设置大于0, 就可以营造向上投抛物体的效果, 该值会随着重力加速度衰减
  125. /// </summary>
  126. public float VerticalSpeed
  127. {
  128. get => _verticalSpeed;
  129. set
  130. {
  131. _verticalSpeed = value;
  132. _hasResilienceVerticalSpeed = false;
  133. }
  134. }
  135.  
  136. private float _verticalSpeed;
  137. /// <summary>
  138. /// 物体投抛时旋转速度, 角度制
  139. /// </summary>
  140. public float ThrowRotationDegreesSpeed { get; set; }
  141.  
  142. /// <summary>
  143. /// 落地之后是否回弹
  144. /// </summary>
  145. public bool Bounce { get; set; } = true;
  146.  
  147. /// <summary>
  148. /// 物体下坠回弹的强度
  149. /// </summary>
  150. public float BounceStrength { get; set; } = 0.5f;
  151.  
  152. /// <summary>
  153. /// 物体下坠回弹后的运动速度衰减量
  154. /// </summary>
  155. public float BounceSpeed { get; set; } = 0.75f;
  156.  
  157. /// <summary>
  158. /// 投抛状态下物体碰撞器大小, 如果 (x, y) 都小于 0, 则默认使用 AnimatedSprite 的默认动画第一帧的大小
  159. /// </summary>
  160. [Export]
  161. public Vector2 ThrowCollisionSize { get; set; } = new Vector2(-1, -1);
  162.  
  163. /// <summary>
  164. /// 是否启用垂直方向上的运动模拟, 默认开启, 如果禁用, 那么下落和投抛效果, 同样 Throw() 函数也将失效
  165. /// </summary>
  166. public bool EnableVerticalMotion { get; set; } = true;
  167.  
  168. /// <summary>
  169. /// 是否启用物体更新行为, 默认 true, 如果禁用, 则会停止当前物体的 Process(), PhysicsProcess() 调用, 并且禁用 Collision 节点, 禁用后所有组件也同样被禁用行为
  170. /// </summary>
  171. public bool EnableBehavior
  172. {
  173. get => _enableBehavior;
  174. set
  175. {
  176. if (value != _enableBehavior)
  177. {
  178. _enableBehavior = value;
  179. SetProcess(value);
  180. SetPhysicsProcess(value);
  181. if (value)
  182. {
  183. Collision.Disabled = _enableBehaviorCollisionDisabledFlag;
  184. }
  185. else
  186. {
  187. _enableBehaviorCollisionDisabledFlag = Collision.Disabled;
  188. Collision.Disabled = true;
  189. }
  190. }
  191. }
  192. }
  193.  
  194. /// <summary>
  195. /// 是否启用自定义行为, 默认 true, 如果禁用, 则会停止调用子类重写的 Process(), PhysicsProcess() 函数, 并且当前物体除 MoveController 以外的组件 Process(), PhysicsProcess() 也会停止调用
  196. /// </summary>
  197. public bool EnableCustomBehavior { get; set; } = true;
  198. /// <summary>
  199. /// 所在的 World 对象
  200. /// </summary>
  201. public World World { get; private set; }
  202. // --------------------------------------------------------------------------------
  203.  
  204. //组件集合
  205. private List<KeyValuePair<Type, Component>> _components = new List<KeyValuePair<Type, Component>>();
  206. //上一帧动画名称
  207. private string _prevAnimation;
  208. //上一帧动画
  209. private int _prevAnimationFrame;
  210.  
  211. //播放 Hit 动画
  212. private bool _playHit;
  213. private float _playHitSchedule;
  214.  
  215. //混色shader材质
  216. private ShaderMaterial _blendShaderMaterial;
  217. private ShaderMaterial _shadowBlendShaderMaterial;
  218. //存储投抛该物体时所产生的数据
  219. private ActivityFallData _fallData = new ActivityFallData();
  220. //所在层级
  221. private RoomLayerEnum _currLayer;
  222. //标记字典
  223. private Dictionary<string, object> _signMap;
  224. //开启的协程
  225. private List<CoroutineData> _coroutineList;
  226.  
  227. //物体所在区域
  228. private AffiliationArea _affiliationArea;
  229.  
  230. //是否是第一次下坠
  231. private bool _firstFall = true;
  232. //下坠是否已经结束
  233. private bool _isFallOver = true;
  234.  
  235. //下坠状态碰撞器形状
  236. private RectangleShape2D _throwRectangleShape;
  237.  
  238. //投抛移动速率
  239. private ExternalForce _throwForce;
  240. //落到地上回弹的速度
  241. private float _resilienceVerticalSpeed = 0;
  242. private bool _hasResilienceVerticalSpeed = false;
  243.  
  244. //是否启用物体行为
  245. private bool _enableBehavior = true;
  246. private bool _enableBehaviorCollisionDisabledFlag;
  247.  
  248. private bool _processingBecomesStaticImage = false;
  249.  
  250. // --------------------------------------------------------------------------------
  251. //实例索引
  252. private static long _instanceIndex = 0;
  253.  
  254. //初始化节点
  255. private void _InitNode(RegisterActivityData activityData, World world)
  256. {
  257. #if TOOLS
  258. if (!Engine.IsEditorHint())
  259. {
  260. if (GetType().GetCustomAttributes(typeof(ToolAttribute), false).Length == 0)
  261. {
  262. throw new Exception($"ActivityObject子类'{GetType().FullName}'没有加[Tool]标记!");
  263. }
  264. }
  265. #endif
  266. World = world;
  267. ItemConfig = activityData.Config;
  268. Name = GetType().Name + (_instanceIndex++);
  269. _blendShaderMaterial = AnimatedSprite.Material as ShaderMaterial;
  270. _shadowBlendShaderMaterial = ShadowSprite.Material as ShaderMaterial;
  271. ShadowSprite.Visible = false;
  272. MotionMode = MotionModeEnum.Floating;
  273. MoveController = AddComponent<MoveController>();
  274. MoveController.Enable = !IsStatic;
  275. OnInit();
  276. }
  277.  
  278. /// <summary>
  279. /// 子类重写的 _Ready() 可能会比 _InitNode() 函数调用晚, 所以禁止子类重写, 如需要 _Ready() 类似的功能需重写 OnInit()
  280. /// </summary>
  281. public sealed override void _Ready()
  282. {
  283.  
  284. }
  285.  
  286. /// <summary>
  287. /// 子类需要重写 _EnterTree() 函数, 请重写 EnterTree()
  288. /// </summary>
  289. public sealed override void _EnterTree()
  290. {
  291. #if TOOLS
  292. // 在工具模式下创建的 template 节点自动创建对应的必要子节点
  293. if (Engine.IsEditorHint())
  294. {
  295. _InitNodeInEditor();
  296. return;
  297. }
  298. #endif
  299. EnterTree();
  300. }
  301. /// <summary>
  302. /// 子类需要重写 _ExitTree() 函数, 请重写 ExitTree()
  303. /// </summary>
  304. public sealed override void _ExitTree()
  305. {
  306. #if TOOLS
  307. // 在工具模式下创建的 template 节点自动创建对应的必要子节点
  308. if (Engine.IsEditorHint())
  309. {
  310. return;
  311. }
  312. #endif
  313. ExitTree();
  314. }
  315.  
  316. /// <summary>
  317. /// 显示阴影
  318. /// </summary>
  319. public void ShowShadowSprite()
  320. {
  321. var anim = AnimatedSprite.Animation;
  322. var frame = AnimatedSprite.Frame;
  323. if (_prevAnimation != anim || _prevAnimationFrame != frame)
  324. {
  325. var frames = AnimatedSprite.SpriteFrames;
  326. if (frames != null && frames.HasAnimation(anim))
  327. {
  328. //切换阴影动画
  329. ShadowSprite.Texture = frames.GetFrameTexture(anim, frame);
  330. }
  331. }
  332.  
  333. _prevAnimation = anim;
  334. _prevAnimationFrame = frame;
  335.  
  336. CalcShadow();
  337. ShadowSprite.Visible = true;
  338. }
  339.  
  340. /// <summary>
  341. /// 隐藏阴影
  342. /// </summary>
  343. public void HideShadowSprite()
  344. {
  345. ShadowSprite.Visible = false;
  346. }
  347.  
  348. /// <summary>
  349. /// 设置默认序列帧动画的第一帧
  350. /// </summary>
  351. public void SetDefaultTexture(Texture2D texture)
  352. {
  353. if (AnimatedSprite.SpriteFrames == null)
  354. {
  355. SpriteFrames spriteFrames = new SpriteFrames();
  356. AnimatedSprite.SpriteFrames = spriteFrames;
  357. spriteFrames.AddFrame("default", texture);
  358. }
  359. else
  360. {
  361. SpriteFrames spriteFrames = AnimatedSprite.SpriteFrames;
  362. spriteFrames.SetFrame("default", 0, texture);
  363. }
  364. AnimatedSprite.Play("default");
  365. }
  366.  
  367. /// <summary>
  368. /// 获取默认序列帧动画的第一帧
  369. /// </summary>
  370. public Texture2D GetDefaultTexture()
  371. {
  372. return AnimatedSprite.SpriteFrames.GetFrameTexture("default", 0);
  373. }
  374. /// <summary>
  375. /// 获取当前序列帧动画的 Texture2D
  376. /// </summary>
  377. public Texture2D GetCurrentTexture()
  378. {
  379. var spriteFrames = AnimatedSprite.SpriteFrames;
  380. if (spriteFrames == null)
  381. {
  382. return null;
  383. }
  384. return spriteFrames.GetFrameTexture(AnimatedSprite.Animation, AnimatedSprite.Frame);
  385. }
  386.  
  387. /// <summary>
  388. /// 物体初始化时调用
  389. /// </summary>
  390. public virtual void OnInit()
  391. {
  392. }
  393.  
  394. /// <summary>
  395. /// 进入场景树时调用
  396. /// </summary>
  397. public virtual void EnterTree()
  398. {
  399. }
  400.  
  401. /// <summary>
  402. /// 离开场景树时调用
  403. /// </summary>
  404. public virtual void ExitTree()
  405. {
  406. }
  407. /// <summary>
  408. /// 返回是否能与其他ActivityObject互动
  409. /// </summary>
  410. /// <param name="master">触发者</param>
  411. public virtual CheckInteractiveResult CheckInteractive(ActivityObject master)
  412. {
  413. return new CheckInteractiveResult(this);
  414. }
  415.  
  416. /// <summary>
  417. /// 与其它ActivityObject互动时调用, 如果要检测是否能互动请 CheckInteractive() 函数, 如果直接调用该函数那么属于强制互动行为, 例如子弹碰到物体
  418. /// </summary>
  419. /// <param name="master">触发者</param>
  420. public virtual void Interactive(ActivityObject master)
  421. {
  422. }
  423.  
  424. /// <summary>
  425. /// 开始投抛该物体时调用
  426. /// </summary>
  427. protected virtual void OnThrowStart()
  428. {
  429. }
  430. /// <summary>
  431. /// 投抛该物体达到最高点时调用
  432. /// </summary>
  433. protected virtual void OnThrowMaxHeight(float height)
  434. {
  435. }
  436.  
  437. /// <summary>
  438. /// 投抛状态下第一次接触地面时调用, 之后的回弹落地将不会调用该函数
  439. /// </summary>
  440. protected virtual void OnFirstFallToGround()
  441. {
  442. }
  443.  
  444. /// <summary>
  445. /// 投抛状态下每次接触地面时调用
  446. /// </summary>
  447. protected virtual void OnFallToGround()
  448. {
  449. }
  450.  
  451. /// <summary>
  452. /// 投抛结束时调用
  453. /// </summary>
  454. protected virtual void OnThrowOver()
  455. {
  456. }
  457.  
  458. /// <summary>
  459. /// 当前物体销毁时调用, 销毁物体请调用 Destroy() 函数
  460. /// </summary>
  461. protected virtual void OnDestroy()
  462. {
  463. }
  464.  
  465. /// <summary>
  466. /// 每帧调用一次, 物体的 Process() 会在组件的 Process() 之前调用
  467. /// </summary>
  468. protected virtual void Process(float delta)
  469. {
  470. }
  471. /// <summary>
  472. /// 每帧调用一次, ProcessOver() 会在组件的 Process() 之后调用
  473. /// </summary>
  474. protected virtual void ProcessOver(float delta)
  475. {
  476. }
  477. /// <summary>
  478. /// 每物理帧调用一次, 物体的 PhysicsProcess() 会在组件的 PhysicsProcess() 之前调用
  479. /// </summary>
  480. protected virtual void PhysicsProcess(float delta)
  481. {
  482. }
  483. /// <summary>
  484. /// 每物理帧调用一次, PhysicsProcessOver() 会在组件的 PhysicsProcess() 之后调用
  485. /// </summary>
  486. protected virtual void PhysicsProcessOver(float delta)
  487. {
  488. }
  489. /// <summary>
  490. /// 如果开启 debug, 则每帧调用该函数, 可用于绘制文字线段等
  491. /// </summary>
  492. protected virtual void DebugDraw()
  493. {
  494. }
  495.  
  496. /// <summary>
  497. /// 归属区域发生改变
  498. /// </summary>
  499. protected virtual void OnAffiliationChange()
  500. {
  501. }
  502.  
  503. /// <summary>
  504. /// 返回当物体 CollisionLayer 是否能与 mask 层碰撞
  505. /// </summary>
  506. public bool CollisionWithMask(uint mask)
  507. {
  508. return (CollisionLayer & mask) != 0;
  509. }
  510. /// <summary>
  511. /// 拾起一个 node 节点, 也就是将其从场景树中移除
  512. /// </summary>
  513. public void Pickup()
  514. {
  515. var parent = GetParent();
  516. if (parent != null)
  517. {
  518. if (IsThrowing)
  519. {
  520. StopThrow();
  521. }
  522.  
  523. parent.RemoveChild(this);
  524. }
  525. }
  526.  
  527. /// <summary>
  528. /// 将一个节点扔到地上
  529. /// <param name="layer">放入的层</param>
  530. /// <param name="showShadow">是否显示阴影</param>
  531. /// </summary>
  532. public virtual void PutDown(RoomLayerEnum layer, bool showShadow = true)
  533. {
  534. _currLayer = layer;
  535. var parent = GetParent();
  536. var root = GameApplication.Instance.World.GetRoomLayer(layer);
  537. if (parent != root)
  538. {
  539. if (parent != null)
  540. {
  541. parent.RemoveChild(this);
  542. }
  543.  
  544. this.AddToActivityRoot(layer);
  545. }
  546.  
  547. if (showShadow)
  548. {
  549. if (IsInsideTree())
  550. {
  551. ShowShadowSprite();
  552. }
  553. else
  554. {
  555. //注意需要延时调用
  556. CallDeferred(nameof(ShowShadowSprite));
  557. }
  558. }
  559. else
  560. {
  561. ShadowSprite.Visible = false;
  562. }
  563. }
  564.  
  565. /// <summary>
  566. /// 将一个节点扔到地上
  567. /// </summary>
  568. /// <param name="position">放置的位置</param>
  569. /// <param name="layer">放入的层</param>
  570. /// <param name="showShadow">是否显示阴影</param>
  571. public void PutDown(Vector2 position, RoomLayerEnum layer, bool showShadow = true)
  572. {
  573. PutDown(layer);
  574. Position = position;
  575. }
  576.  
  577. /// <summary>
  578. /// 将该节点投抛出去
  579. /// </summary>
  580. /// <param name="altitude">初始高度</param>
  581. /// <param name="verticalSpeed">纵轴速度</param>
  582. /// <param name="velocity">移动速率</param>
  583. /// <param name="rotateSpeed">旋转速度</param>
  584. public void Throw(float altitude, float verticalSpeed, Vector2 velocity, float rotateSpeed)
  585. {
  586. var parent = GetParent();
  587. if (parent == null)
  588. {
  589. GameApplication.Instance.World.YSortLayer.AddChild(this);
  590. }
  591. else if (parent != GameApplication.Instance.World.YSortLayer)
  592. {
  593. parent.RemoveChild(this);
  594. GameApplication.Instance.World.YSortLayer.AddChild(this);
  595. }
  596. Altitude = altitude;
  597. //Position = Position + new Vector2(0, altitude);
  598. VerticalSpeed = verticalSpeed;
  599. ThrowRotationDegreesSpeed = rotateSpeed;
  600. if (_throwForce != null)
  601. {
  602. MoveController.RemoveForce(_throwForce);
  603. }
  604.  
  605. _throwForce = new ExternalForce("throw");
  606. _throwForce.Velocity = velocity;
  607. MoveController.AddForce(_throwForce);
  608.  
  609. InitThrowData();
  610. }
  611.  
  612. /// <summary>
  613. /// 将该节点投抛出去
  614. /// </summary>
  615. /// <param name="position">初始位置</param>
  616. /// <param name="altitude">初始高度</param>
  617. /// <param name="verticalSpeed">纵轴速度</param>
  618. /// <param name="velocity">移动速率</param>
  619. /// <param name="rotateSpeed">旋转速度</param>
  620. public void Throw(Vector2 position, float altitude, float verticalSpeed, Vector2 velocity, float rotateSpeed)
  621. {
  622. GlobalPosition = position;
  623. Throw(altitude, verticalSpeed, velocity, rotateSpeed);
  624. }
  625.  
  626.  
  627. /// <summary>
  628. /// 强制停止投抛运动
  629. /// </summary>
  630. public void StopThrow()
  631. {
  632. _isFallOver = true;
  633. RestoreCollision();
  634. }
  635.  
  636. /// <summary>
  637. /// 往当前物体上挂载一个组件
  638. /// </summary>
  639. public T AddComponent<T>() where T : Component, new()
  640. {
  641. var component = new T();
  642. _components.Add(new KeyValuePair<Type, Component>(typeof(T), component));
  643. component.ActivityInstance = this;
  644. return component;
  645. }
  646.  
  647. /// <summary>
  648. /// 移除一个组件, 并且销毁
  649. /// </summary>
  650. /// <param name="component">组件对象</param>
  651. public void RemoveComponent(Component component)
  652. {
  653. for (int i = 0; i < _components.Count; i++)
  654. {
  655. if (_components[i].Value == component)
  656. {
  657. _components.RemoveAt(i);
  658. component.Destroy();
  659. return;
  660. }
  661. }
  662. }
  663.  
  664. /// <summary>
  665. /// 根据类型获取一个组件
  666. /// </summary>
  667. public Component GetComponent(Type type)
  668. {
  669. for (int i = 0; i < _components.Count; i++)
  670. {
  671. var temp = _components[i];
  672. if (temp.Key == type)
  673. {
  674. return temp.Value;
  675. }
  676. }
  677.  
  678. return null;
  679. }
  680.  
  681. /// <summary>
  682. /// 根据类型获取一个组件
  683. /// </summary>
  684. public T GetComponent<T>() where T : Component
  685. {
  686. var component = GetComponent(typeof(T));
  687. if (component == null) return null;
  688. return (T)component;
  689. }
  690.  
  691. /// <summary>
  692. /// 设置混色材质的颜色
  693. /// </summary>
  694. public void SetBlendColor(Color color)
  695. {
  696. _blendShaderMaterial.SetShaderParameter("blend", color);
  697. }
  698.  
  699. /// <summary>
  700. /// 获取混色材质的颜色
  701. /// </summary>
  702. public Color GetBlendColor()
  703. {
  704. return _blendShaderMaterial.GetShaderParameter("blend").AsColor();
  705. }
  706. /// <summary>
  707. /// 设置混色材质的强度
  708. /// </summary>
  709. public void SetBlendSchedule(float value)
  710. {
  711. _blendShaderMaterial.SetShaderParameter("schedule", value);
  712. }
  713.  
  714. /// <summary>
  715. /// 获取混色材质的强度
  716. /// </summary>
  717. public float GetBlendSchedule()
  718. {
  719. return _blendShaderMaterial.GetShaderParameter("schedule").AsSingle();
  720. }
  721.  
  722. /// <summary>
  723. /// 设置透明度
  724. /// </summary>
  725. public void SetBlendAlpha(float value)
  726. {
  727. _blendShaderMaterial.SetShaderParameter("alpha", value);
  728. _shadowBlendShaderMaterial.SetShaderParameter("alpha", value);
  729. }
  730. /// <summary>
  731. /// 获取透明度
  732. /// </summary>
  733. public float SetBlendAlpha()
  734. {
  735. return _blendShaderMaterial.GetShaderParameter("alpha").AsSingle();
  736. }
  737. /// <summary>
  738. /// 每帧调用一次, 为了防止子类覆盖 _Process(), 给 _Process() 加上了 sealed, 子类需要帧循环函数请重写 Process() 函数
  739. /// </summary>
  740. public sealed override void _Process(double delta)
  741. {
  742. #if TOOLS
  743. if (Engine.IsEditorHint())
  744. {
  745. return;
  746. }
  747. #endif
  748. var newDelta = (float)delta;
  749. if (EnableCustomBehavior)
  750. {
  751. Process(newDelta);
  752. }
  753. //更新组件
  754. if (_components.Count > 0)
  755. {
  756. if (EnableCustomBehavior) //启用所有组件
  757. {
  758. var arr = _components.ToArray();
  759. for (int i = 0; i < arr.Length; i++)
  760. {
  761. if (IsDestroyed) return;
  762. var temp = arr[i].Value;
  763. if (temp != null && temp.ActivityInstance == this && temp.Enable)
  764. {
  765. if (!temp.IsReady)
  766. {
  767. temp.Ready();
  768. temp.IsReady = true;
  769. }
  770.  
  771. temp.Process(newDelta);
  772. }
  773. }
  774. }
  775. else //只更新 MoveController 组件
  776. {
  777. if (MoveController.Enable)
  778. {
  779. if (!MoveController.IsReady)
  780. {
  781. MoveController.Ready();
  782. MoveController.IsReady = true;
  783. }
  784.  
  785. MoveController.Process(newDelta);
  786. }
  787. }
  788. }
  789.  
  790. // 下坠判定
  791. if (Altitude > 0 || VerticalSpeed != 0)
  792. {
  793. if (_isFallOver) // 没有处于下坠状态, 则进入下坠状态
  794. {
  795. InitThrowData();
  796. }
  797. else
  798. {
  799. if (EnableVerticalMotion) //如果启用了纵向运动, 则更新运动
  800. {
  801. GlobalRotationDegrees = GlobalRotationDegrees + ThrowRotationDegreesSpeed * newDelta;
  802.  
  803. var ysp = VerticalSpeed;
  804.  
  805. _altitude += VerticalSpeed * newDelta;
  806. _verticalSpeed -= GameConfig.G * newDelta;
  807.  
  808. //当高度大于16时, 显示在所有物体上
  809. if (Altitude >= 16)
  810. {
  811. AnimatedSprite.ZIndex = 20;
  812. }
  813. else
  814. {
  815. AnimatedSprite.ZIndex = 0;
  816. }
  817. //达到最高点
  818. if (ysp > 0 && ysp * VerticalSpeed < 0)
  819. {
  820. OnThrowMaxHeight(Altitude);
  821. }
  822.  
  823. //落地判断
  824. if (Altitude <= 0)
  825. {
  826. _altitude = 0;
  827.  
  828. //第一次接触地面
  829. if (_firstFall)
  830. {
  831. _firstFall = false;
  832. OnFirstFallToGround();
  833. }
  834.  
  835. MoveController.ScaleAllForce(BounceSpeed);
  836. //如果落地高度不够低, 再抛一次
  837. if (Bounce && (!_hasResilienceVerticalSpeed || _resilienceVerticalSpeed > 5))
  838. {
  839. if (!_hasResilienceVerticalSpeed)
  840. {
  841. _hasResilienceVerticalSpeed = true;
  842. _resilienceVerticalSpeed = -VerticalSpeed * BounceStrength;
  843. }
  844. else
  845. {
  846. if (_resilienceVerticalSpeed < 25)
  847. {
  848. _resilienceVerticalSpeed = _resilienceVerticalSpeed * BounceStrength * 0.4f;
  849. }
  850. else
  851. {
  852. _resilienceVerticalSpeed = _resilienceVerticalSpeed * BounceStrength;
  853. }
  854. }
  855. _verticalSpeed = _resilienceVerticalSpeed;
  856. ThrowRotationDegreesSpeed = ThrowRotationDegreesSpeed * BounceStrength;
  857. _isFallOver = false;
  858.  
  859. OnFallToGround();
  860. }
  861. else //结束
  862. {
  863. _verticalSpeed = 0;
  864.  
  865. if (_throwForce != null)
  866. {
  867. MoveController.RemoveForce(_throwForce);
  868. _throwForce = null;
  869. }
  870. _isFallOver = true;
  871. OnFallToGround();
  872. ThrowOver();
  873. }
  874. }
  875. }
  876.  
  877. //计算精灵位置
  878. CalcThrowAnimatedPosition();
  879. }
  880. }
  881.  
  882. //阴影
  883. if (ShadowSprite.Visible)
  884. {
  885. //更新阴影贴图, 使其和动画一致
  886. var anim = AnimatedSprite.Animation;
  887. var frame = AnimatedSprite.Frame;
  888. if (_prevAnimation != anim || _prevAnimationFrame != frame)
  889. {
  890. //切换阴影动画
  891. ShadowSprite.Texture = AnimatedSprite.SpriteFrames.GetFrameTexture(anim, AnimatedSprite.Frame);
  892. }
  893.  
  894. _prevAnimation = anim;
  895. _prevAnimationFrame = frame;
  896.  
  897. //计算阴影
  898. CalcShadow();
  899. }
  900.  
  901. // Hit 动画
  902. if (_playHit)
  903. {
  904. if (_playHitSchedule < 0.05f)
  905. {
  906. _blendShaderMaterial.SetShaderParameter("schedule", 1);
  907. }
  908. else if (_playHitSchedule < 0.15f)
  909. {
  910. _blendShaderMaterial.SetShaderParameter("schedule", Mathf.Lerp(1, 0, (_playHitSchedule - 0.05f) / 0.1f));
  911. }
  912. if (_playHitSchedule >= 0.15f)
  913. {
  914. _blendShaderMaterial.SetShaderParameter("schedule", 0);
  915. _playHitSchedule = 0;
  916. _playHit = false;
  917. }
  918. else
  919. {
  920. _playHitSchedule += newDelta;
  921. }
  922. }
  923. //协程更新
  924. if (_coroutineList != null)
  925. {
  926. ProxyCoroutineHandler.ProxyUpdateCoroutine(ref _coroutineList, newDelta);
  927. }
  928.  
  929. ProcessOver(newDelta);
  930. //调试绘制
  931. if (IsDebug)
  932. {
  933. QueueRedraw();
  934. }
  935. }
  936.  
  937. /// <summary>
  938. /// 每物理帧调用一次, 为了防止子类覆盖 _PhysicsProcess(), 给 _PhysicsProcess() 加上了 sealed, 子类需要帧循环函数请重写 PhysicsProcess() 函数
  939. /// </summary>
  940. public sealed override void _PhysicsProcess(double delta)
  941. {
  942. #if TOOLS
  943. if (Engine.IsEditorHint())
  944. {
  945. return;
  946. }
  947. #endif
  948. var newDelta = (float)delta;
  949. if (EnableCustomBehavior)
  950. {
  951. PhysicsProcess(newDelta);
  952. }
  953. //更新组件
  954. if (_components.Count > 0)
  955. {
  956. if (EnableCustomBehavior) //启用所有组件
  957. {
  958. var arr = _components.ToArray();
  959. for (int i = 0; i < arr.Length; i++)
  960. {
  961. if (IsDestroyed) return;
  962. var temp = arr[i].Value;
  963. if (temp != null && temp.ActivityInstance == this && temp.Enable)
  964. {
  965. if (!temp.IsReady)
  966. {
  967. temp.Ready();
  968. temp.IsReady = true;
  969. }
  970.  
  971. temp.PhysicsProcess(newDelta);
  972. }
  973. }
  974. }
  975. else //只更新 MoveController 组件
  976. {
  977. if (MoveController.Enable)
  978. {
  979. if (!MoveController.IsReady)
  980. {
  981. MoveController.Ready();
  982. MoveController.IsReady = true;
  983. }
  984.  
  985. MoveController.PhysicsProcess(newDelta);
  986. }
  987. }
  988. }
  989.  
  990. PhysicsProcessOver(newDelta);
  991. }
  992.  
  993. /// <summary>
  994. /// 绘制函数, 子类不允许重写, 需要绘制函数请重写 DebugDraw()
  995. /// </summary>
  996. public sealed override void _Draw()
  997. {
  998. #if TOOLS
  999. if (Engine.IsEditorHint())
  1000. {
  1001. return;
  1002. }
  1003. #endif
  1004. if (IsDebug)
  1005. {
  1006. DebugDraw();
  1007. var arr = _components.ToArray();
  1008. for (int i = 0; i < arr.Length; i++)
  1009. {
  1010. if (IsDestroyed) return;
  1011. var temp = arr[i].Value;
  1012. if (temp != null && temp.ActivityInstance == this && temp.Enable)
  1013. {
  1014. temp.DebugDraw();
  1015. }
  1016. }
  1017. }
  1018. }
  1019.  
  1020. /// <summary>
  1021. /// 重新计算物体阴影的位置和旋转信息, 无论是否显示阴影
  1022. /// </summary>
  1023. public void CalcShadow()
  1024. {
  1025. //缩放
  1026. ShadowSprite.Scale = AnimatedSprite.Scale;
  1027. //阴影角度
  1028. ShadowSprite.Rotation = 0;
  1029. //阴影位置计算
  1030. var pos = AnimatedSprite.GlobalPosition;
  1031. ShadowSprite.GlobalPosition = new Vector2(pos.X + ShadowOffset.X, pos.Y + ShadowOffset.Y + Altitude);
  1032. }
  1033.  
  1034. //计算位置
  1035. private void CalcThrowAnimatedPosition()
  1036. {
  1037. if (Scale.Y < 0)
  1038. {
  1039. var pos = new Vector2(_fallData.OriginSpritePosition.X, -_fallData.OriginSpritePosition.Y);
  1040. AnimatedSprite.GlobalPosition = GlobalPosition + new Vector2(0, -Altitude) - pos.Rotated(Rotation + Mathf.Pi);
  1041. }
  1042. else
  1043. {
  1044. AnimatedSprite.GlobalPosition = GlobalPosition + new Vector2(0, -Altitude) + _fallData.OriginSpritePosition.Rotated(Rotation);
  1045. }
  1046. }
  1047.  
  1048.  
  1049. /// <summary>
  1050. /// 销毁物体
  1051. /// </summary>
  1052. public void Destroy()
  1053. {
  1054. if (IsDestroyed)
  1055. {
  1056. return;
  1057. }
  1058.  
  1059. IsDestroyed = true;
  1060. if (AffiliationArea != null)
  1061. {
  1062. AffiliationArea.RemoveItem(this);
  1063. }
  1064. QueueFree();
  1065. OnDestroy();
  1066.  
  1067. var arr = _components.ToArray();
  1068. for (int i = 0; i < arr.Length; i++)
  1069. {
  1070. arr[i].Value?.Destroy();
  1071. }
  1072. if (AffiliationArea != null)
  1073. {
  1074. AffiliationArea.RemoveItem(this);
  1075. }
  1076. }
  1077.  
  1078. /// <summary>
  1079. /// 延时销毁
  1080. /// </summary>
  1081. public void DelayDestroy()
  1082. {
  1083. CallDeferred(nameof(Destroy));
  1084. }
  1085.  
  1086. /// <summary>
  1087. /// 继承指定物体的运动速率
  1088. /// </summary>
  1089. public void InheritVelocity(ActivityObject other, float scale = 0.5f)
  1090. {
  1091. MoveController.AddVelocity(other.Velocity * scale);
  1092. }
  1093.  
  1094. /// <summary>
  1095. /// 触发投抛动作
  1096. /// </summary>
  1097. private void Throw()
  1098. {
  1099. var parent = GetParent();
  1100. //投抛时必须要加入 YSortLayer 节点下
  1101. if (parent == null)
  1102. {
  1103. this.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  1104. }
  1105. else if (parent == GameApplication.Instance.World.NormalLayer)
  1106. {
  1107. parent.RemoveChild(this);
  1108. this.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  1109. }
  1110.  
  1111. CalcThrowAnimatedPosition();
  1112. //显示阴影
  1113. ShowShadowSprite();
  1114.  
  1115. if (EnableVerticalMotion)
  1116. {
  1117. OnThrowStart();
  1118. }
  1119. }
  1120.  
  1121. /// <summary>
  1122. /// 设置下坠状态下的碰撞器
  1123. /// </summary>
  1124. private void SetFallCollision()
  1125. {
  1126. if (_fallData != null && _fallData.UseOrigin)
  1127. {
  1128. _fallData.OriginShape = Collision.Shape;
  1129. _fallData.OriginPosition = Collision.Position;
  1130. _fallData.OriginRotation = Collision.Rotation;
  1131. _fallData.OriginScale = Collision.Scale;
  1132. _fallData.OriginZIndex = ZIndex;
  1133. _fallData.OriginSpritePosition = AnimatedSprite.Position;
  1134. _fallData.OriginCollisionEnable = Collision.Disabled;
  1135. _fallData.OriginCollisionPosition = Collision.Position;
  1136. _fallData.OriginCollisionRotation = Collision.Rotation;
  1137. _fallData.OriginCollisionScale = Collision.Scale;
  1138. _fallData.OriginCollisionMask = CollisionMask;
  1139. _fallData.OriginCollisionLayer = CollisionLayer;
  1140.  
  1141. if (_throwRectangleShape == null)
  1142. {
  1143. _throwRectangleShape = new RectangleShape2D();
  1144. }
  1145. Collision.Shape = _throwRectangleShape;
  1146. Collision.Position = Vector2.Zero;
  1147. Collision.Rotation = 0;
  1148. Collision.Scale = Vector2.One;
  1149. ZIndex = 0;
  1150. Collision.Disabled = false;
  1151. Collision.Position = Vector2.Zero;
  1152. Collision.Rotation = 0;
  1153. Collision.Scale = Vector2.One;
  1154. CollisionMask = 1;
  1155. CollisionLayer = PhysicsLayer.Throwing;
  1156. _fallData.UseOrigin = false;
  1157. }
  1158. }
  1159.  
  1160. /// <summary>
  1161. /// 重置碰撞器
  1162. /// </summary>
  1163. private void RestoreCollision()
  1164. {
  1165. if (_fallData != null && !_fallData.UseOrigin)
  1166. {
  1167. Collision.Shape = _fallData.OriginShape;
  1168. Collision.Position = _fallData.OriginPosition;
  1169. Collision.Rotation = _fallData.OriginRotation;
  1170. Collision.Scale = _fallData.OriginScale;
  1171. ZIndex = _fallData.OriginZIndex;
  1172. AnimatedSprite.Position = _fallData.OriginSpritePosition;
  1173. Collision.Disabled = _fallData.OriginCollisionEnable;
  1174. Collision.Position = _fallData.OriginCollisionPosition;
  1175. Collision.Rotation = _fallData.OriginCollisionRotation;
  1176. Collision.Scale = _fallData.OriginCollisionScale;
  1177. CollisionMask = _fallData.OriginCollisionMask;
  1178. CollisionLayer = _fallData.OriginCollisionLayer;
  1179.  
  1180. _fallData.UseOrigin = true;
  1181. }
  1182. }
  1183.  
  1184. /// <summary>
  1185. /// 投抛结束
  1186. /// </summary>
  1187. private void ThrowOver()
  1188. {
  1189. var parent = GetParent();
  1190. var roomLayer = GameApplication.Instance.World.GetRoomLayer(_currLayer);
  1191. if (parent != roomLayer)
  1192. {
  1193. parent.RemoveChild(this);
  1194. roomLayer.AddChild(this);
  1195. }
  1196. RestoreCollision();
  1197.  
  1198. OnThrowOver();
  1199. }
  1200.  
  1201. //初始化投抛状态数据
  1202. private void InitThrowData()
  1203. {
  1204. SetFallCollision();
  1205.  
  1206. _isFallOver = false;
  1207. _firstFall = true;
  1208. _hasResilienceVerticalSpeed = false;
  1209. _resilienceVerticalSpeed = 0;
  1210. if (ThrowCollisionSize.X < 0 && ThrowCollisionSize.Y < 0)
  1211. {
  1212. _throwRectangleShape.Size = GetDefaultTexture().GetSize();
  1213. }
  1214. else
  1215. {
  1216. _throwRectangleShape.Size = ThrowCollisionSize;
  1217. }
  1218.  
  1219. Throw();
  1220. }
  1221.  
  1222. /// <summary>
  1223. /// 设置标记, 用于在物体上记录自定义数据
  1224. /// </summary>
  1225. /// <param name="name">标记名称</param>
  1226. /// <param name="v">存入值</param>
  1227. public void SetSign(string name, object v)
  1228. {
  1229. if (_signMap == null)
  1230. {
  1231. _signMap = new Dictionary<string, object>();
  1232. }
  1233.  
  1234. _signMap[name] = v;
  1235. }
  1236.  
  1237. /// <summary>
  1238. /// 返回是否存在指定名称的标记数据
  1239. /// </summary>
  1240. public bool HasSign(string name)
  1241. {
  1242. return _signMap == null ? false : _signMap.ContainsKey(name);
  1243. }
  1244.  
  1245. /// <summary>
  1246. /// 根据名称获取标记值
  1247. /// </summary>
  1248. public object GetSign(string name)
  1249. {
  1250. if (_signMap == null)
  1251. {
  1252. return null;
  1253. }
  1254.  
  1255. _signMap.TryGetValue(name, out var value);
  1256. return value;
  1257. }
  1258.  
  1259. /// <summary>
  1260. /// 根据名称获取标记值
  1261. /// </summary>
  1262. public T GetSign<T>(string name)
  1263. {
  1264. if (_signMap == null)
  1265. {
  1266. return default;
  1267. }
  1268.  
  1269. _signMap.TryGetValue(name, out var value);
  1270. if (value is T v)
  1271. {
  1272. return v;
  1273. }
  1274. return default;
  1275. }
  1276.  
  1277. /// <summary>
  1278. /// 根据名称删除标记
  1279. /// </summary>
  1280. public void RemoveSign(string name)
  1281. {
  1282. if (_signMap != null)
  1283. {
  1284. _signMap.Remove(name);
  1285. }
  1286. }
  1287.  
  1288. /// <summary>
  1289. /// 播放受伤动画, 该动画不与 Animation 节点的动画冲突
  1290. /// </summary>
  1291. public void PlayHitAnimation()
  1292. {
  1293. _playHit = true;
  1294. _playHitSchedule = 0;
  1295. }
  1296.  
  1297. /// <summary>
  1298. /// 开启一个协程, 返回协程 id, 协程是在普通帧执行的, 支持: 协程嵌套, WaitForSeconds, WaitForFixedProcess, Task, SignalAwaiter
  1299. /// </summary>
  1300. public long StartCoroutine(IEnumerator able)
  1301. {
  1302. return ProxyCoroutineHandler.ProxyStartCoroutine(ref _coroutineList, able);
  1303. }
  1304.  
  1305. /// <summary>
  1306. /// 根据协程 id 停止协程
  1307. /// </summary>
  1308. public void StopCoroutine(long coroutineId)
  1309. {
  1310. ProxyCoroutineHandler.ProxyStopCoroutine(ref _coroutineList, coroutineId);
  1311. }
  1312. /// <summary>
  1313. /// 停止所有协程
  1314. /// </summary>
  1315. public void StopAllCoroutine()
  1316. {
  1317. ProxyCoroutineHandler.ProxyStopAllCoroutine(ref _coroutineList);
  1318. }
  1319.  
  1320. /// <summary>
  1321. /// 延时指定时间调用一个回调函数
  1322. /// </summary>
  1323. public void CallDelay(float delayTime, Action cb)
  1324. {
  1325. StartCoroutine(_CallDelay(delayTime, cb));
  1326. }
  1327. /// <summary>
  1328. /// 延时指定时间调用一个回调函数
  1329. /// </summary>
  1330. public void CallDelay<T1>(float delayTime, Action<T1> cb, T1 arg1)
  1331. {
  1332. StartCoroutine(_CallDelay(delayTime, cb, arg1));
  1333. }
  1334. /// <summary>
  1335. /// 延时指定时间调用一个回调函数
  1336. /// </summary>
  1337. public void CallDelay<T1, T2>(float delayTime, Action<T1, T2> cb, T1 arg1, T2 arg2)
  1338. {
  1339. StartCoroutine(_CallDelay(delayTime, cb, arg1, arg2));
  1340. }
  1341. /// <summary>
  1342. /// 延时指定时间调用一个回调函数
  1343. /// </summary>
  1344. public void CallDelay<T1, T2, T3>(float delayTime, Action<T1, T2, T3> cb, T1 arg1, T2 arg2, T3 arg3)
  1345. {
  1346. StartCoroutine(_CallDelay(delayTime, cb, arg1, arg2, arg3));
  1347. }
  1348.  
  1349. private IEnumerator _CallDelay(float delayTime, Action cb)
  1350. {
  1351. yield return new WaitForSeconds(delayTime);
  1352. cb();
  1353. }
  1354. private IEnumerator _CallDelay<T1>(float delayTime, Action<T1> cb, T1 arg1)
  1355. {
  1356. yield return new WaitForSeconds(delayTime);
  1357. cb(arg1);
  1358. }
  1359. private IEnumerator _CallDelay<T1, T2>(float delayTime, Action<T1, T2> cb, T1 arg1, T2 arg2)
  1360. {
  1361. yield return new WaitForSeconds(delayTime);
  1362. cb(arg1, arg2);
  1363. }
  1364. private IEnumerator _CallDelay<T1, T2, T3>(float delayTime, Action<T1, T2, T3> cb, T1 arg1, T2 arg2, T3 arg3)
  1365. {
  1366. yield return new WaitForSeconds(delayTime);
  1367. cb(arg1,arg2, arg3);
  1368. }
  1369.  
  1370. /// <summary>
  1371. /// 将当前 ActivityObject 变成静态图像绘制到地面上, 用于优化渲染大量物体<br/>
  1372. /// 调用该函数后会排队进入渲染队列, 并且禁用所有行为, 当渲染完成后会销毁当前对象, 也就是调用 Destroy() 函数<br/>
  1373. /// </summary>
  1374. public void BecomesStaticImage()
  1375. {
  1376. if (AffiliationArea == null)
  1377. {
  1378. GD.PrintErr($"调用函数: BecomesStaticImage() 失败, 物体{Name}没有归属区域, 无法确定绘制到哪个ImageCanvas上");
  1379. return;
  1380. }
  1381.  
  1382. if (_processingBecomesStaticImage)
  1383. {
  1384. return;
  1385. }
  1386.  
  1387. _processingBecomesStaticImage = true;
  1388. EnableBehavior = false;
  1389. var staticImageCanvas = AffiliationArea.RoomInfo.StaticImageCanvas;
  1390. var (x, y) = staticImageCanvas.ToImageCanvasPosition(GlobalPosition);
  1391. staticImageCanvas.CanvasSprite.DrawActivityObjectInCanvas(this, x, y, () =>
  1392. {
  1393. Destroy();
  1394. });
  1395. }
  1396.  
  1397. /// <summary>
  1398. /// 是否正在处理成为静态图片
  1399. /// </summary>
  1400. public bool IsProcessingBecomesStaticImage()
  1401. {
  1402. return _processingBecomesStaticImage;
  1403. }
  1404. }