Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / bullet / Bullet.cs
  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.  
  42. // 最大飞行距离
  43. private float MaxDistance;
  44.  
  45. // 子弹飞行速度
  46. private float FlySpeed;
  47.  
  48. //当前子弹已经飞行的距离
  49. private float CurrFlyDistance = 0;
  50.  
  51. /// <summary>
  52. /// 初始化子弹属性
  53. /// </summary>
  54. /// <param name="trigger">触发开火的角色</param>
  55. /// <param name="weapon">射出该子弹的武器</param>
  56. /// <param name="speed">速度</param>
  57. /// <param name="maxDistance">最大飞行距离</param>
  58. /// <param name="position">位置</param>
  59. /// <param name="rotation">角度</param>
  60. /// <param name="targetLayer">攻击目标层级</param>
  61. public void Init(Role trigger, Weapon weapon, float speed, float maxDistance, Vector2 position, float rotation, uint targetLayer)
  62. {
  63. Weapon = weapon;
  64. Role = weapon.Master;
  65. AttackLayer = targetLayer;
  66. CollisionArea.AreaEntered += OnArea2dEntered;
  67. //只有玩家使用该武器才能获得正常速度的子弹
  68. if (trigger != null && !trigger.IsAi)
  69. {
  70. FlySpeed = speed;
  71. }
  72. else
  73. {
  74. FlySpeed = speed * weapon.AiUseAttribute.AiBulletSpeedScale;
  75. }
  76. MaxDistance = maxDistance;
  77. Position = position;
  78. Rotation = rotation;
  79. ShadowOffset = new Vector2(0, 5);
  80. BasisVelocity = new Vector2(FlySpeed, 0).Rotated(Rotation);
  81. //如果子弹会对玩家造成伤害, 则显示红色描边
  82. // if (Player.Current.CollisionWithMask(targetLayer))
  83. // {
  84. // ShowOutline = true;
  85. // OutlineColor = new Color(1, 0, 0, 0.9f);
  86. // }
  87. }
  88.  
  89. /// <summary>
  90. /// 播放子弹消失的特效
  91. /// </summary>
  92. public virtual void PlayDisappearEffect()
  93. {
  94. var packedScene = ResourceManager.Load<PackedScene>(ResourcePath.prefab_effect_weapon_BulletDisappear_tscn);
  95. var node = packedScene.Instantiate<Node2D>();
  96. node.GlobalPosition = GlobalPosition;
  97. node.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  98. }
  99. protected override void PhysicsProcessOver(float delta)
  100. {
  101. //移动
  102. var lastSlideCollision = GetLastSlideCollision();
  103. //撞到墙
  104. if (lastSlideCollision != null)
  105. {
  106. //创建粒子特效
  107. var packedScene = ResourceManager.Load<PackedScene>(ResourcePath.prefab_effect_weapon_BulletSmoke_tscn);
  108. var smoke = packedScene.Instantiate<GpuParticles2D>();
  109. smoke.GlobalPosition = lastSlideCollision.GetPosition();
  110. smoke.GlobalRotation = lastSlideCollision.GetNormal().Angle();
  111. smoke.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  112.  
  113. Destroy();
  114. return;
  115. }
  116. //距离太大, 自动销毁
  117. CurrFlyDistance += FlySpeed * delta;
  118. if (CurrFlyDistance >= MaxDistance)
  119. {
  120. PlayDisappearEffect();
  121. Destroy();
  122. }
  123. }
  124. private void OnArea2dEntered(Area2D other)
  125. {
  126. var role = other.AsActivityObject<Role>();
  127. if (role != null)
  128. {
  129. var packedScene = ResourceManager.Load<PackedScene>(ResourcePath.prefab_effect_weapon_BulletDisappear_tscn);
  130. var node = packedScene.Instantiate<Node2D>();
  131. node.GlobalPosition = GlobalPosition;
  132. node.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  133.  
  134. //计算子弹造成的伤害
  135. var damage = Utils.Random.RandomRangeInt(MinHarm, MaxHarm);
  136. if (Role != null)
  137. {
  138. damage = Role.RoleState.CallCalcDamageEvent(damage);
  139. }
  140. role.CallDeferred(nameof(Role.Hurt), damage, Rotation);
  141. Destroy();
  142. }
  143. }
  144. }