Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / bullet / explode / Explode.cs
  1.  
  2. using Config;
  3. using Godot;
  4.  
  5. /// <summary>
  6. /// 爆炸
  7. /// </summary>
  8. public partial class Explode : Area2D, IPoolItem
  9. {
  10. public bool IsRecycled { get; set; }
  11. public string Logotype { get; set; }
  12.  
  13. public bool IsDestroyed { get; private set; }
  14.  
  15. /// <summary>
  16. /// 动画播放器
  17. /// </summary>
  18. public AnimationPlayer AnimationPlayer { get; private set; }
  19. /// <summary>
  20. /// 碰撞器
  21. /// </summary>
  22. public CollisionShape2D CollisionShape { get; private set; }
  23. /// <summary>
  24. /// 碰撞器形状对象
  25. /// </summary>
  26. public CircleShape2D CircleShape { get; private set; }
  27.  
  28. /// <summary>
  29. /// 爆炸攻击的层级
  30. /// </summary>
  31. public uint AttackLayer { get; private set; }
  32.  
  33. /// <summary>
  34. /// 产生爆炸的子弹数据
  35. /// </summary>
  36. public BulletData BulletData { get; private set; }
  37.  
  38. private bool _init = false;
  39. private float _hitRadius;
  40. private int _harm;
  41. private float _repelledRadius;
  42. private float _maxRepelled;
  43. public void Destroy()
  44. {
  45. if (IsDestroyed)
  46. {
  47. return;
  48. }
  49.  
  50. IsDestroyed = true;
  51. QueueFree();
  52. }
  53.  
  54. /// <summary>
  55. /// 初始化爆炸数据
  56. /// </summary>
  57. /// <param name="bulletData">产生爆炸的子弹数据</param>
  58. /// <param name="attackLayer">攻击的层级</param>
  59. /// <param name="hitRadius">伤害半径</param>
  60. /// <param name="harm">造成的伤害</param>
  61. /// <param name="repelledRadius">击退半径</param>
  62. /// <param name="maxRepelled">最大击退速度</param>
  63. public void Init(BulletData bulletData, uint attackLayer, float hitRadius, int harm, float repelledRadius, float maxRepelled)
  64. {
  65. if (!_init)
  66. {
  67. _init = true;
  68. AnimationPlayer = GetNode<AnimationPlayer>("AnimationPlayer");
  69. CollisionShape = GetNode<CollisionShape2D>("CollisionShape2D");
  70. CircleShape = (CircleShape2D)CollisionShape.Shape;
  71. AnimationPlayer.AnimationFinished += OnAnimationFinish;
  72. AreaEntered += OnArea2dEntered;
  73. BodyEntered += OnBodyEntered;
  74. }
  75.  
  76. BulletData = bulletData;
  77. AttackLayer = attackLayer;
  78. _hitRadius = hitRadius;
  79. _harm = harm;
  80. _repelledRadius = repelledRadius;
  81. _maxRepelled = maxRepelled;
  82. CollisionMask = attackLayer | PhysicsLayer.Prop | PhysicsLayer.Debris;
  83. CircleShape.Radius = Mathf.Max(hitRadius, maxRepelled);
  84.  
  85. //冲击波
  86. var affiliationArea = bulletData.TriggerRole?.AffiliationArea;
  87. if (affiliationArea != null)
  88. {
  89. ShockWave(affiliationArea);
  90. }
  91. }
  92. /// <summary>
  93. /// 播放爆炸, triggerRole 为触发该爆炸的角色
  94. /// </summary>
  95. public void RunPlay(Role triggerRole = null)
  96. {
  97. GameCamera.Main.CreateShake(new Vector2(6, 6), 0.7f, true);
  98. AnimationPlayer.Play(AnimatorNames.Play);
  99. //播放爆炸音效
  100. SoundManager.PlaySoundByConfig("explosion0002", Position, triggerRole);
  101. }
  102.  
  103. //爆炸冲击波
  104. private void ShockWave(AffiliationArea affiliationArea)
  105. {
  106. var position = Position;
  107. var freezeSprites = affiliationArea.RoomInfo.StaticSprite.CollisionCircle(position, _repelledRadius, true);
  108. foreach (var freezeSprite in freezeSprites)
  109. {
  110. var temp = freezeSprite.Position - position;
  111. freezeSprite.ActivityObject.MoveController.AddForce(temp.Normalized() * _maxRepelled * (_repelledRadius - temp.Length()) / _repelledRadius);
  112. }
  113. }
  114.  
  115. public void OnReclaim()
  116. {
  117. GetParent().CallDeferred(Node.MethodName.RemoveChild, this);
  118. }
  119.  
  120. public void OnLeavePool()
  121. {
  122. }
  123.  
  124. private void OnAnimationFinish(StringName name)
  125. {
  126. if (name == AnimatorNames.Play)
  127. {
  128. ObjectPool.Reclaim(this);
  129. }
  130. }
  131.  
  132. private void OnBodyEntered(Node2D node)
  133. {
  134. if (node is IHurt hurt)
  135. {
  136. HandlerCollision(hurt);
  137. }
  138. else if (node is Bullet bullet) //是子弹
  139. {
  140. if (bullet is BoomBullet boomBullet) //如果是爆炸子弹, 则直接销毁
  141. {
  142. boomBullet.PlayBoom();
  143. }
  144. bullet.Destroy();
  145. }
  146. }
  147. private void OnArea2dEntered(Area2D other)
  148. {
  149. if (other is IHurt hurt)
  150. {
  151. HandlerCollision(hurt);
  152. }
  153. }
  154.  
  155. private void HandlerCollision(IHurt hurt)
  156. {
  157. var temp = hurt.GetPosition() - Position;
  158. var len = temp.Length();
  159. var angle = temp.Angle();
  160.  
  161. if (len <= _hitRadius) //在伤害半径内
  162. {
  163. hurt.Hurt(BulletData.TriggerRole.IsDestroyed ? null : BulletData.TriggerRole, _harm, angle);
  164. }
  165. if (len <= _repelledRadius) //击退半径内
  166. {
  167. var o = hurt.GetActivityObject();
  168. if (o != null)
  169. {
  170. var repelled = (_repelledRadius - len) / _repelledRadius * _maxRepelled;
  171. o.AddRepelForce(Vector2.FromAngle(angle) * repelled);
  172. }
  173. }
  174. }
  175. }