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