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