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