Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / bullet / explode / Explode.cs
@小李xl 小李xl on 3 Nov 2023 4 KB 爆炸影响弹壳
  1.  
  2. using Godot;
  3.  
  4. /// <summary>
  5. /// 爆炸
  6. /// </summary>
  7. public partial class Explode : Area2D, IPoolItem
  8. {
  9. public bool IsRecycled { get; set; }
  10. public string Logotype { get; set; }
  11.  
  12. public bool IsDestroyed { get; private set; }
  13.  
  14. /// <summary>
  15. /// 动画播放器
  16. /// </summary>
  17. public AnimationPlayer AnimationPlayer { get; private set; }
  18. /// <summary>
  19. /// 碰撞器
  20. /// </summary>
  21. public CollisionShape2D CollisionShape { get; private set; }
  22. /// <summary>
  23. /// 碰撞器形状对象
  24. /// </summary>
  25. public CircleShape2D CircleShape { get; private set; }
  26.  
  27. /// <summary>
  28. /// 爆炸攻击的层级
  29. /// </summary>
  30. public uint AttackLayer { get; private set; }
  31.  
  32.  
  33. private bool _init = false;
  34. private AffiliationArea _affiliationArea;
  35. private float _hitRadius;
  36. private int _minHarm;
  37. private int _maxHarm;
  38. private float _repelledRadius;
  39. private float _maxRepelled;
  40. public void Destroy()
  41. {
  42. if (IsDestroyed)
  43. {
  44. return;
  45. }
  46.  
  47. IsDestroyed = true;
  48. QueueFree();
  49. }
  50.  
  51. /// <summary>
  52. /// 初始化爆炸数据
  53. /// </summary>
  54. /// <param name="affiliationArea">爆炸所在区域</param>
  55. /// <param name="attackLayer">攻击的层级</param>
  56. /// <param name="hitRadius">伤害半径</param>
  57. /// <param name="minHarm">最小伤害</param>
  58. /// <param name="maxHarm">最大伤害</param>
  59. /// <param name="repelledRadius">击退半径</param>
  60. /// <param name="maxRepelled">最大击退速度</param>
  61. public void Init(AffiliationArea affiliationArea, uint attackLayer, float hitRadius, int minHarm, int maxHarm, float repelledRadius, float maxRepelled)
  62. {
  63. if (!_init)
  64. {
  65. _init = true;
  66. AnimationPlayer = GetNode<AnimationPlayer>("AnimationPlayer");
  67. CollisionShape = GetNode<CollisionShape2D>("CollisionShape2D");
  68. CircleShape = (CircleShape2D)CollisionShape.Shape;
  69. AnimationPlayer.AnimationFinished += OnAnimationFinish;
  70. BodyEntered += OnBodyEntered;
  71. }
  72.  
  73. _affiliationArea = affiliationArea;
  74. AttackLayer = attackLayer;
  75. _hitRadius = hitRadius;
  76. _minHarm = minHarm;
  77. _maxHarm = maxHarm;
  78. _repelledRadius = repelledRadius;
  79. _maxRepelled = maxRepelled;
  80. CollisionMask = attackLayer | PhysicsLayer.Prop | PhysicsLayer.Throwing | PhysicsLayer.Debris;
  81. CircleShape.Radius = Mathf.Max(hitRadius, maxRepelled);
  82.  
  83. Check();
  84. }
  85. public void RunPlay()
  86. {
  87. GameCamera.Main.CreateShake(new Vector2(6, 6), 0.7f, true);
  88. AnimationPlayer.Play(AnimatorNames.Play);
  89. }
  90.  
  91. public void Check()
  92. {
  93. var position = Position;
  94. var freezeSprites = _affiliationArea.RoomInfo.StaticSprite.CollisionCircle(position, _repelledRadius, true);
  95. foreach (var freezeSprite in freezeSprites)
  96. {
  97. var temp = freezeSprite.Position - position;
  98. freezeSprite.ActivityObject.MoveController.AddForce(temp.Normalized() * _maxRepelled * (_repelledRadius - temp.Length()) / _repelledRadius);
  99. }
  100. }
  101.  
  102. public void OnReclaim()
  103. {
  104. GetParent().RemoveChild(this);
  105. }
  106.  
  107. public void OnLeavePool()
  108. {
  109. }
  110.  
  111. private void OnAnimationFinish(StringName name)
  112. {
  113. if (name == AnimatorNames.Play)
  114. {
  115. ObjectPool.Reclaim(this);
  116. }
  117. }
  118.  
  119. private void OnBodyEntered(Node2D node)
  120. {
  121. var o = node.AsActivityObject();
  122. if (o != null)
  123. {
  124. var temp = o.Position - Position;
  125. var len = temp.Length();
  126. var angle = temp.Angle();
  127. if (len <= _repelledRadius) //击退半径内
  128. {
  129. var repelled = (_repelledRadius - len) / _repelledRadius * _maxRepelled;
  130. o.MoveController.SetAllVelocity(Vector2.Zero);
  131. o.MoveController.AddForce(Vector2.FromAngle(angle) * repelled);
  132. }
  133.  
  134. if (o is Role role)
  135. {
  136. if (len <= _hitRadius) //在伤害半径内
  137. {
  138. role.CallDeferred(nameof(role.Hurt), Utils.Random.RandomRangeInt(_minHarm, _maxHarm), angle);
  139. }
  140. }
  141. }
  142. }
  143. }