Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / bullet / Bullet.cs
@小李xl 小李xl on 19 Sep 2023 5 KB 武器子弹击退效果
  1. using Godot;
  2.  
  3. /// <summary>
  4. /// 子弹类
  5. /// </summary>
  6. [Tool]
  7. public partial class Bullet : ActivityObject
  8. {
  9. /// <summary>
  10. /// 碰撞区域
  11. /// </summary>
  12. [Export, ExportFillNode]
  13. public Area2D CollisionArea { get; set; }
  14.  
  15. /// <summary>
  16. /// 攻击的层级
  17. /// </summary>
  18. public uint AttackLayer
  19. {
  20. get => CollisionArea.CollisionMask;
  21. set => CollisionArea.CollisionMask = value;
  22. }
  23.  
  24. /// <summary>
  25. /// 发射该子弹的武器
  26. /// </summary>
  27. public Weapon Weapon { get; private set; }
  28. /// <summary>
  29. /// 发射该子弹的角色
  30. /// </summary>
  31. public Role Role { get; private set; }
  32.  
  33. /// <summary>
  34. /// 最小伤害
  35. /// </summary>
  36. public int MinHarm { get; set; } = 4;
  37. /// <summary>
  38. /// 最大伤害
  39. /// </summary>
  40. public int MaxHarm { get; set; } = 4;
  41. /// <summary>
  42. /// 发射该子弹的角色
  43. /// </summary>
  44. public Role Trigger { get; private set; }
  45.  
  46. // 最大飞行距离
  47. private float MaxDistance;
  48.  
  49. // 子弹飞行速度
  50. private float FlySpeed;
  51.  
  52. //当前子弹已经飞行的距离
  53. private float CurrFlyDistance = 0;
  54.  
  55. /// <summary>
  56. /// 初始化子弹属性
  57. /// </summary>
  58. /// <param name="trigger">触发开火的角色</param>
  59. /// <param name="weapon">射出该子弹的武器</param>
  60. /// <param name="speed">速度</param>
  61. /// <param name="maxDistance">最大飞行距离</param>
  62. /// <param name="position">位置</param>
  63. /// <param name="rotation">角度</param>
  64. /// <param name="targetLayer">攻击目标层级</param>
  65. public void Init(Role trigger, Weapon weapon, float speed, float maxDistance, Vector2 position, float rotation, uint targetLayer)
  66. {
  67. Trigger = trigger;
  68. Weapon = weapon;
  69. Role = weapon.Master;
  70. AttackLayer = targetLayer;
  71. CollisionArea.AreaEntered += OnArea2dEntered;
  72. if (trigger != null && !trigger.IsAi) //只有玩家使用该武器才能获得正常速度的子弹
  73. {
  74. FlySpeed = speed;
  75. }
  76. else
  77. {
  78. FlySpeed = speed * weapon.AiUseAttribute.AiBulletSpeedScale;
  79. }
  80. MaxDistance = maxDistance;
  81. Position = position;
  82. Rotation = rotation;
  83. ShadowOffset = new Vector2(0, 5);
  84. BasisVelocity = new Vector2(FlySpeed, 0).Rotated(Rotation);
  85. //如果子弹会对玩家造成伤害, 则显示红色描边
  86. // if (Player.Current.CollisionWithMask(targetLayer))
  87. // {
  88. // ShowOutline = true;
  89. // OutlineColor = new Color(1, 0, 0, 0.9f);
  90. // }
  91. }
  92.  
  93. /// <summary>
  94. /// 播放子弹消失的特效
  95. /// </summary>
  96. public virtual void PlayDisappearEffect()
  97. {
  98. var packedScene = ResourceManager.Load<PackedScene>(ResourcePath.prefab_effect_weapon_BulletDisappear_tscn);
  99. var node = packedScene.Instantiate<Node2D>();
  100. node.GlobalPosition = GlobalPosition;
  101. node.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  102. }
  103. protected override void PhysicsProcessOver(float delta)
  104. {
  105. //移动
  106. var lastSlideCollision = GetLastSlideCollision();
  107. //撞到墙
  108. if (lastSlideCollision != null)
  109. {
  110. //创建粒子特效
  111. var packedScene = ResourceManager.Load<PackedScene>(ResourcePath.prefab_effect_weapon_BulletSmoke_tscn);
  112. var smoke = packedScene.Instantiate<GpuParticles2D>();
  113. smoke.GlobalPosition = lastSlideCollision.GetPosition();
  114. smoke.GlobalRotation = lastSlideCollision.GetNormal().Angle();
  115. smoke.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  116.  
  117. Destroy();
  118. return;
  119. }
  120. //距离太大, 自动销毁
  121. CurrFlyDistance += FlySpeed * delta;
  122. if (CurrFlyDistance >= MaxDistance)
  123. {
  124. PlayDisappearEffect();
  125. Destroy();
  126. }
  127. }
  128. private void OnArea2dEntered(Area2D other)
  129. {
  130. var role = other.AsActivityObject<Role>();
  131. if (role != null)
  132. {
  133. var packedScene = ResourceManager.Load<PackedScene>(ResourcePath.prefab_effect_weapon_BulletDisappear_tscn);
  134. var node = packedScene.Instantiate<Node2D>();
  135. node.GlobalPosition = GlobalPosition;
  136. node.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  137.  
  138. //计算子弹造成的伤害
  139. var damage = Utils.Random.RandomRangeInt(MinHarm, MaxHarm);
  140. if (Role != null)
  141. {
  142. damage = Role.RoleState.CallCalcDamageEvent(damage);
  143. }
  144.  
  145. //击退
  146. if (role is not Player) //目标不是玩家才会触发击退
  147. {
  148. var attr = Trigger != null && !Trigger.IsAi ? Weapon.PlayerUseAttribute : Weapon.AiUseAttribute;
  149. var repel = Utils.Random.RandomConfigRange(attr.RepelRnage);
  150. role.MoveController.AddForce(Vector2.FromAngle(BasisVelocity.Angle()) * repel, repel * 2);
  151. }
  152. //造成伤害
  153. role.CallDeferred(nameof(Role.Hurt), damage, Rotation);
  154. Destroy();
  155. }
  156. }
  157. }