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