Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / bullet / laser / Laser.cs
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using Config;
  4. using Godot;
  5.  
  6. /// <summary>
  7. /// 激光子弹
  8. /// </summary>
  9. public partial class Laser : Area2D, IBullet
  10. {
  11. public CollisionShape2D Collision { get; private set; }
  12. public Sprite2D LineSprite { get; private set; }
  13. public RectangleShape2D Shape { get; private set; }
  14.  
  15. public uint AttackLayer
  16. {
  17. get => CollisionMask;
  18. set => CollisionMask = value;
  19. }
  20. public Weapon Weapon { get; set; }
  21. public ExcelConfig.BulletBase BulletBase { get; set; }
  22. public Role TriggerRole { get; set; }
  23. /// <summary>
  24. /// 最小伤害
  25. /// </summary>
  26. public int MinHarm { get; set; } = 4;
  27. /// <summary>
  28. /// 最大伤害
  29. /// </summary>
  30. public int MaxHarm { get; set; } = 4;
  31. public bool IsDestroyed { get; private set; }
  32. public float Width { get; set; }
  33. //开启的协程
  34. private List<CoroutineData> _coroutineList;
  35. private float _pixelScale;
  36. private float _speed = 2000;
  37.  
  38. public override void _Ready()
  39. {
  40. Collision = GetNodeOrNull<CollisionShape2D>("CollisionShape2D");
  41. Collision.Disabled = true;
  42. Shape = Collision.Shape as RectangleShape2D;
  43. LineSprite = GetNodeOrNull<Sprite2D>("LineSprite");
  44. _pixelScale = 1f / LineSprite.Texture.GetHeight();
  45.  
  46. AreaEntered += OnArea2dEntered;
  47. }
  48. public void Init(Weapon weapon, uint attackLayer, Vector2 position, float rotation, float width, float distance)
  49. {
  50. TriggerRole = weapon.TriggerRole;
  51. Weapon = weapon;
  52. AttackLayer = attackLayer;
  53. Position = position;
  54. Rotation = rotation;
  55.  
  56. //计算射线最大距离, 也就是撞到墙壁的距离
  57. var targetPosition = position + Vector2.FromAngle(rotation) * distance;
  58. var parameters = PhysicsRayQueryParameters2D.Create(position, targetPosition, PhysicsLayer.Wall);
  59. var result = GetWorld2D().DirectSpaceState.IntersectRay(parameters);
  60. if (result != null && result.TryGetValue("position", out var point))
  61. {
  62. distance = position.DistanceTo((Vector2)point);
  63. }
  64. Collision.SetDeferred(CollisionShape2D.PropertyName.Disabled, false);
  65. Collision.Position = Vector2.Zero;
  66. Shape.Size = Vector2.Zero;;
  67. LineSprite.Scale = new Vector2(0, width * _pixelScale);
  68.  
  69. //如果子弹会对玩家造成伤害, 则显示成红色
  70. if (Player.Current.CollisionWithMask(attackLayer))
  71. {
  72. LineSprite.Modulate = new Color(2.5f, 0.5f, 0.5f);
  73. }
  74. //激光飞行时间
  75. var time = distance / _speed;
  76.  
  77. var tween = CreateTween();
  78. tween.SetParallel();
  79. tween.TweenProperty(LineSprite, "scale", new Vector2(distance, width * _pixelScale), time);
  80. tween.TweenProperty(Collision, "position", new Vector2(distance * 0.5f, 0), time);
  81. tween.TweenProperty(Shape, "size", new Vector2(distance, width), time);
  82. tween.Chain();
  83. //持续时间
  84. // tween.TweenInterval(0.2f);
  85. // tween.Chain();
  86. tween.TweenCallback(Callable.From(() =>
  87. {
  88. Collision.SetDeferred(CollisionShape2D.PropertyName.Disabled, false);
  89. }));
  90. tween.Chain();
  91. tween.TweenProperty(LineSprite, "scale", new Vector2(distance, 0), 0.3f);
  92. tween.Chain();
  93. tween.TweenCallback(Callable.From(() =>
  94. {
  95. Destroy();
  96. }));
  97. tween.Play();
  98. }
  99.  
  100. public override void _Process(double delta)
  101. {
  102. ProxyCoroutineHandler.ProxyUpdateCoroutine(ref _coroutineList, (float)delta);
  103. }
  104.  
  105. public void Destroy()
  106. {
  107. if (IsDestroyed)
  108. {
  109. return;
  110. }
  111. QueueFree();
  112. }
  113. private void OnArea2dEntered(Area2D other)
  114. {
  115. var role = other.AsActivityObject<Role>();
  116. if (role != null)
  117. {
  118. //计算子弹造成的伤害
  119. var damage = Utils.Random.RandomRangeInt(MinHarm, MaxHarm);
  120. if (TriggerRole != null)
  121. {
  122. damage = TriggerRole.RoleState.CallCalcDamageEvent(damage);
  123. }
  124. //造成伤害
  125. role.CallDeferred(nameof(Role.Hurt), damage, Rotation);
  126. }
  127. }
  128.  
  129. public long StartCoroutine(IEnumerator able)
  130. {
  131. return ProxyCoroutineHandler.ProxyStartCoroutine(ref _coroutineList, able);
  132. }
  133.  
  134. public void StopCoroutine(long coroutineId)
  135. {
  136. ProxyCoroutineHandler.ProxyStopCoroutine(ref _coroutineList, coroutineId);
  137. }
  138.  
  139. public bool IsCoroutineOver(long coroutineId)
  140. {
  141. return ProxyCoroutineHandler.ProxyIsCoroutineOver(ref _coroutineList, coroutineId);
  142. }
  143.  
  144. public void StopAllCoroutine()
  145. {
  146. ProxyCoroutineHandler.ProxyStopAllCoroutine(ref _coroutineList);
  147. }
  148. }