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 Weapon Weapon { get; private set; }
  19. /// <summary>
  20. /// 发射该子弹的角色
  21. /// </summary>
  22. public Role Role { get; private set; }
  23.  
  24. /// <summary>
  25. /// 最小伤害
  26. /// </summary>
  27. public int MinHarm { get; set; } = 4;
  28. /// <summary>
  29. /// 最大伤害
  30. /// </summary>
  31. public int MaxHarm { get; set; } = 4;
  32.  
  33. // 最大飞行距离
  34. private float MaxDistance;
  35.  
  36. // 子弹飞行速度
  37. private float FlySpeed;
  38.  
  39. //当前子弹已经飞行的距离
  40. private float CurrFlyDistance = 0;
  41.  
  42. public void Init(Weapon weapon, float speed, float maxDistance, Vector2 position, float rotation, uint targetLayer)
  43. {
  44. Weapon = weapon;
  45. Role = weapon.Master;
  46. CollisionArea.CollisionMask = targetLayer;
  47. CollisionArea.AreaEntered += OnArea2dEntered;
  48. //只有玩家使用该武器才能获得正常速度的子弹
  49. if (weapon.Master is Player)
  50. {
  51. FlySpeed = speed;
  52. }
  53. else
  54. {
  55. FlySpeed = speed * weapon.Attribute.AiBulletSpeedScale;
  56. }
  57. MaxDistance = maxDistance;
  58. Position = position;
  59. Rotation = rotation;
  60. ShadowOffset = new Vector2(0, 5);
  61.  
  62. BasisVelocity = new Vector2(FlySpeed, 0).Rotated(Rotation);
  63. }
  64.  
  65. protected override void PhysicsProcessOver(float delta)
  66. {
  67. //移动
  68. var lastSlideCollision = GetLastSlideCollision();
  69. //撞到墙
  70. if (lastSlideCollision != null)
  71. {
  72. //创建粒子特效
  73. var packedScene = ResourceManager.Load<PackedScene>(ResourcePath.prefab_effect_BulletSmoke_tscn);
  74. var smoke = packedScene.Instantiate<GpuParticles2D>();
  75. smoke.GlobalPosition = lastSlideCollision.GetPosition();
  76. smoke.GlobalRotation = lastSlideCollision.GetNormal().Angle();
  77. smoke.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  78.  
  79. Destroy();
  80. return;
  81. }
  82. //距离太大, 自动销毁
  83. CurrFlyDistance += FlySpeed * delta;
  84. if (CurrFlyDistance >= MaxDistance)
  85. {
  86. var packedScene = ResourceManager.Load<PackedScene>(ResourcePath.prefab_effect_BulletDisappear_tscn);
  87. var node = packedScene.Instantiate<Node2D>();
  88. node.GlobalPosition = GlobalPosition;
  89. node.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  90. Destroy();
  91. }
  92. }
  93.  
  94. private void OnArea2dEntered(Area2D other)
  95. {
  96. var role = other.AsActivityObject<Role>();
  97. if (role != null)
  98. {
  99. var packedScene = ResourceManager.Load<PackedScene>(ResourcePath.prefab_effect_BulletDisappear_tscn);
  100. var node = packedScene.Instantiate<Node2D>();
  101. node.GlobalPosition = GlobalPosition;
  102. node.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  103.  
  104. //计算子弹造成的伤害
  105. var damage = Utils.Random.RandomRangeInt(MinHarm, MaxHarm);
  106. if (Role != null)
  107. {
  108. var d = damage;
  109. damage = Role.RoleState.CallCalcDamageEvent(damage);
  110. GD.Print($"原伤害: {d}, 计算伤害: {damage}");
  111. }
  112. role.CallDeferred(nameof(Role.Hurt), damage, Rotation);
  113. Destroy();
  114. }
  115. }
  116. }