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