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