Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / weapon / knife / Knife.cs
  1.  
  2. using Godot;
  3.  
  4. /// <summary>
  5. /// 近战武器,刀
  6. /// </summary>
  7. [Tool]
  8. public partial class Knife : Weapon
  9. {
  10. /// <summary>
  11. /// 近战攻击范围
  12. /// </summary>
  13. [Export]
  14. public int AttackRange { get; set; } = 41;
  15.  
  16. /// <summary>
  17. /// 开始蓄力时武器抬起角度
  18. /// </summary>
  19. [Export]
  20. public int BeginChargeAngle { get; set; } = 120;
  21. private Area2D _hitArea;
  22. private int _attackIndex = 0;
  23. private CollisionPolygon2D _collisionPolygon;
  24. public override void OnInit()
  25. {
  26. base.OnInit();
  27.  
  28. //没有Master时不能触发开火
  29. NoMasterCanTrigger = false;
  30. _hitArea = GetNode<Area2D>("HitArea");
  31. _collisionPolygon = new CollisionPolygon2D();
  32. var a = Mathf.Abs(-BeginChargeAngle + Attribute.UpliftAngle);
  33. var ca = Utils.ConvertAngle(-a / 2f);
  34. _collisionPolygon.Polygon = Utils.CreateSectorPolygon(ca, AttackRange, a, 6);
  35. _hitArea.AddChild(_collisionPolygon);
  36. _hitArea.Monitoring = false;
  37. _hitArea.Monitorable = false;
  38. _hitArea.BodyEntered += OnBodyEntered;
  39. _hitArea.AreaEntered += OnArea2dEntered;
  40.  
  41. //禁用自动播放动画
  42. IsAutoPlaySpriteFrames = false;
  43. }
  44.  
  45. protected override void Process(float delta)
  46. {
  47. base.Process(delta);
  48. if (IsActive)
  49. {
  50. //让碰撞节点与武器挂载节点位置保持一致, 而不跟着武器走
  51. _hitArea.GlobalPosition = Master.MountPoint.GlobalPosition;
  52. }
  53. }
  54.  
  55. protected override void PhysicsProcess(float delta)
  56. {
  57. base.PhysicsProcess(delta);
  58. //过去两个物理帧后就能关闭碰撞了
  59. if (++_attackIndex >= 2)
  60. {
  61. _hitArea.Monitoring = false;
  62. }
  63. }
  64.  
  65. protected override void OnBeginCharge()
  66. {
  67. //开始蓄力时武器角度
  68. RotationDegrees = -BeginChargeAngle;
  69. }
  70.  
  71. protected override void OnFire()
  72. {
  73. Debug.Log("近战武器攻击! 蓄力时长: " + GetTriggerChargeTime() + ", 扳机按下时长: " + GetTriggerDownTime());
  74. //更新碰撞层级
  75. _hitArea.CollisionMask = GetAttackLayer() | PhysicsLayer.Bullet;
  76. //启用碰撞
  77. _hitArea.Monitoring = true;
  78. _attackIndex = 0;
  79.  
  80. if (IsActive) //被使用
  81. {
  82. //播放挥刀特效
  83. SpecialEffectManager.PlaySpriteFrames(
  84. Master,
  85. ResourcePath.resource_spriteFrames_weapon_Weapon0004_hit_tres, "default",
  86. Master.MountPoint.Position,
  87. Master.MountPoint.Rotation + Mathf.DegToRad(Attribute.UpliftAngle + 60),
  88. AnimatedSprite.Scale,
  89. new Vector2(17, 4), 1
  90. );
  91. }
  92.  
  93.  
  94. if (Master == Player.Current)
  95. {
  96. var r = Master.MountPoint.RotationDegrees;
  97. //创建屏幕抖动
  98. if (Master.Face == FaceDirection.Right)
  99. {
  100. //GameCamera.Main.DirectionalShake(Vector2.FromAngle(Mathf.DegToRad(r - 90)) * 5);
  101. GameCamera.Main.DirectionalShake(Vector2.FromAngle(Mathf.DegToRad(r - 180)) * Attribute.CameraShake);
  102. }
  103. else
  104. {
  105. //GameCamera.Main.DirectionalShake(Vector2.FromAngle(Mathf.DegToRad(270 - r)) * 5);
  106. GameCamera.Main.DirectionalShake(Vector2.FromAngle(Mathf.DegToRad(-r)) * Attribute.CameraShake);
  107. }
  108. }
  109. }
  110.  
  111. protected override void OnShoot(float fireRotation)
  112. {
  113. }
  114.  
  115. protected override int UseAmmoCount()
  116. {
  117. //这里要做判断, 如果没有碰到敌人, 则不消耗弹药 (耐久)
  118. return 0;
  119. }
  120.  
  121. private void OnBodyEntered(Node2D body)
  122. {
  123. if (body is IHurt hurt)
  124. {
  125. HandlerCollision(hurt);
  126. }
  127. else if (body is Bullet bullet) //攻击子弹
  128. {
  129. var attackLayer = bullet.AttackLayer;
  130. if (TriggerRole != null && TriggerRole.CollisionWithMask(attackLayer)) //是攻击玩家的子弹
  131. {
  132. //反弹子弹
  133. bullet.OnPlayDisappearEffect();
  134. bullet.MoveController.ScaleAllVelocity(-1);
  135. bullet.Rotation += Mathf.Pi;
  136. bullet.AttackLayer = TriggerRole.AttackLayer;
  137. bullet.RefreshBulletColor(false);
  138. }
  139. }
  140. }
  141. private void OnArea2dEntered(Area2D area)
  142. {
  143. if (area is IHurt hurt)
  144. {
  145. HandlerCollision(hurt);
  146. }
  147. }
  148.  
  149. private void HandlerCollision(IHurt hurt)
  150. {
  151. var damage = Utils.Random.RandomConfigRange(Attribute.Bullet.HarmRange);
  152. //计算子弹造成的伤害
  153. if (TriggerRole != null)
  154. {
  155. damage = TriggerRole.RoleState.CalcDamage(damage);
  156. }
  157. //击退
  158. var attr = GetUseAttribute(TriggerRole);
  159. var repel = Utils.Random.RandomConfigRange(attr.Bullet.RepelRange);
  160. //计算击退
  161. if (TriggerRole != null)
  162. {
  163. repel = TriggerRole.RoleState.CalcBulletRepel(repel);
  164. }
  165. var globalPosition = GlobalPosition;
  166. if (repel != 0)
  167. {
  168. var o = hurt.GetActivityObject();
  169. if (o != null && o is not Player) //不是玩家才能被击退
  170. {
  171. Vector2 position;
  172. if (TriggerRole != null)
  173. {
  174. position = o.GlobalPosition - TriggerRole.MountPoint.GlobalPosition;
  175. }
  176. else
  177. {
  178. position = o.GlobalPosition - globalPosition;
  179. }
  180. var v2 = position.Normalized() * repel;
  181. o.AddRepelForce(v2);
  182. }
  183. }
  184. //造成伤害
  185. hurt.Hurt(TriggerRole, damage, (hurt.GetPosition() - globalPosition).Angle());
  186. }
  187. }