Newer
Older
DungeonShooting / src / gun / Gun.cs
@小李xl 小李xl on 17 May 2022 4 KB 第一次提交
  1. using Godot;
  2. using System;
  3.  
  4. public class Gun : Area2D
  5. {
  6. /// <summary>
  7. /// 开火回调事件
  8. /// </summary>
  9. public event Action<Gun> FireEvent;
  10.  
  11. /// <summary>
  12. /// 属性数据
  13. /// </summary>
  14. public GunAttribute Attribute
  15. {
  16. get
  17. {
  18. if (_attribute == null)
  19. {
  20. throw new Exception("请先调用Init来初始化枪的属性");
  21. }
  22. return _attribute;
  23. }
  24. private set => _attribute = value;
  25. }
  26. private GunAttribute _attribute;
  27.  
  28. /// <summary>
  29. /// 枪的图片
  30. /// </summary>
  31. public Sprite Sprite { get; private set; }
  32.  
  33. /// <summary>
  34. /// 枪攻击的目标阵营
  35. /// </summary>
  36. public CampEnum TargetCamp { get; set; }
  37. /// <summary>
  38. /// 开火点
  39. /// </summary>
  40. public Position2D FirePoint { get; private set; }
  41. /// <summary>
  42. /// 原点
  43. /// </summary>
  44. public Position2D OriginPoint { get; private set; }
  45.  
  46. /// <summary>
  47. /// 枪的当前散射半径
  48. /// </summary>
  49. public float CurrScatteringRange { get; private set; } = 0;
  50.  
  51. //是否按下
  52. private bool triggerFlag = false;
  53. private float fireInterval = 0;
  54. private float fireAngle = 0;
  55. private float attackTimer = 0;
  56. private bool attackFlag = false;
  57. private int downFrame = 0;
  58. //子弹
  59. private PackedScene bulletPacked;
  60.  
  61. public override void _EnterTree()
  62. {
  63. Sprite = GetNode<Sprite>("Sprite");
  64. FirePoint = GetNode<Position2D>("FirePoint");
  65. OriginPoint = GetNode<Position2D>("OriginPoint");
  66. }
  67.  
  68. public override void _Process(float delta)
  69. {
  70. downFrame = triggerFlag ? downFrame : 0;
  71. // 攻击的计时器
  72. if (attackTimer > 0)
  73. {
  74. attackTimer -= delta;
  75. }
  76. else if (!attackFlag && attackTimer < 0)
  77. {
  78. attackTimer = 0;
  79. }
  80.  
  81. if (!attackFlag && attackTimer <= 0)
  82. {
  83. CurrScatteringRange = Mathf.Max(CurrScatteringRange - Attribute.ScatteringRangeBackSpeed * delta, Attribute.StartScatteringRange);
  84. }
  85. triggerFlag = false;
  86. attackFlag = false;
  87.  
  88. //枪身回归
  89. Position = Position.MoveToward(Vector2.Zero, 35 * delta);
  90. if (fireInterval == 0)
  91. {
  92. RotationDegrees = 0;
  93. }
  94. else
  95. {
  96. RotationDegrees = Mathf.Lerp(0, fireAngle, attackTimer / fireInterval);
  97. }
  98. }
  99.  
  100. public void Init(GunAttribute attribute)
  101. {
  102. Attribute = attribute;
  103. //更新图片
  104. var texture = ResourceLoader.Load<Texture>(attribute.Sprite);
  105. Sprite.Texture = texture;
  106. //子弹
  107. bulletPacked = ResourceLoader.Load<PackedScene>(attribute.Bullet);
  108. //开火位置
  109. FirePoint.Position = new Vector2(attribute.BarrelLength, FirePoint.Position.y);
  110. }
  111.  
  112. /// <summary>
  113. /// 扳机函数, 调用即视为扣动扳机
  114. /// </summary>
  115. public void Trigger()
  116. {
  117. //是否第一帧按下
  118. var justDown = downFrame++ == 0;
  119.  
  120. if (Attribute.ContinuousShoot || justDown)
  121. {
  122. if (attackTimer <= 0)
  123. {
  124. fireInterval = 60 / Attribute.FiringSpeed;
  125. attackTimer += fireInterval;
  126. Fire();
  127. //当前的散射半径
  128. CurrScatteringRange = Mathf.Min(CurrScatteringRange + Attribute.ScatteringRangeAddValue, Attribute.FinalScatteringRange);
  129. //枪的旋转角度
  130. RotationDegrees -= Attribute.UpliftAngle;
  131. fireAngle = RotationDegrees;
  132. //枪身位置
  133. Position = new Vector2(Mathf.Max(-Attribute.MaxBacklash, Position.x - MathUtils.RandRange(Attribute.MinBacklash, Attribute.MaxBacklash)), Position.y);
  134.  
  135. if (FireEvent != null)
  136. {
  137. FireEvent(this);
  138. }
  139. }
  140. attackFlag = true;
  141. }
  142. triggerFlag = true;
  143. }
  144.  
  145. protected virtual void Fire()
  146. {
  147. //开火发射的子弹数量
  148. var bulletCount = MathUtils.RandRangeInt(Attribute.MaxFireBulletCount, Attribute.MinFireBulletCount);
  149. //枪口角度
  150. var angle = new Vector2(GameConfig.ScatteringDistance, CurrScatteringRange).Angle();
  151.  
  152. //创建子弹
  153. for (int i = 0; i < bulletCount; i++)
  154. {
  155. //先算枪口方向
  156. Rotation = (float)GD.RandRange(-angle, angle);
  157.  
  158. //创建子弹
  159. var bullet = bulletPacked.Instance<Bullet>();
  160. bullet.GlobalPosition = FirePoint.GlobalPosition;
  161. bullet.Rotation = (FirePoint.GlobalPosition - OriginPoint.GlobalPosition).Angle();
  162. GetTree().CurrentScene.AddChild(bullet);
  163.  
  164. //飞行距离
  165. var distance = MathUtils.RandRange(Attribute.MinDistance, Attribute.MaxDistance);
  166. //初始化子弹数据
  167. bullet.Init(TargetCamp, distance, Colors.White);
  168. }
  169. }
  170. }