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