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