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