You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Bullet.cs 9.8 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. using Preparation.Interface;
  2. using Preparation.Utility;
  3. using System;
  4. namespace GameClass.GameObj
  5. {
  6. public abstract class Bullet : ObjOfCharacter
  7. {
  8. /// <summary>
  9. /// //攻击力
  10. /// </summary>
  11. public abstract int AP { get; }
  12. public abstract int Speed { get; }
  13. private readonly bool hasSpear;
  14. /// <summary>
  15. /// 是否有矛
  16. /// </summary>
  17. public bool HasSpear => hasSpear;
  18. /// <summary>
  19. /// 与THUAI4不同的一个攻击判定方案,通过这个函数判断爆炸时能否伤害到target
  20. /// </summary>
  21. /// <param name="target">被尝试攻击者</param>
  22. /// <returns>是否可以攻击到</returns>
  23. public abstract bool CanAttack(GameObj target);
  24. protected override bool IgnoreCollideExecutor(IGameObj targetObj)
  25. {
  26. if (targetObj.Type == GameObjType.BirthPoint || targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet)
  27. return true;
  28. return false;
  29. }
  30. public Bullet(Character player, int radius) :
  31. base(player.Position, radius, PlaceType.Null, GameObjType.Bullet)
  32. {
  33. this.CanMove = true;
  34. this.moveSpeed = this.Speed;
  35. this.hasSpear = player.HasSpear;
  36. this.Parent = player;
  37. }
  38. public override bool IsRigid => true; // 默认为true
  39. public override ShapeType Shape => ShapeType.Circle; // 默认为圆形
  40. public abstract BulletType TypeOfBullet { get; }
  41. }
  42. internal sealed class AtomBomb : Bullet
  43. {
  44. public AtomBomb(Character player, int radius = GameData.bulletRadius) :
  45. base(player, radius)
  46. {
  47. }
  48. public const double BulletBombRange = GameData.basicBulletBombRange / 3 * 7;
  49. public const double BulletAttackRange = GameData.basicAttackRange / 9 * 7;
  50. public override int AP => GameData.basicAp / 3 * 7;
  51. public override int Speed => GameData.basicBulletMoveSpeed / 3 * 2;
  52. public override bool CanAttack(GameObj target)
  53. {
  54. // 圆形攻击范围
  55. return XY.Distance(this.Position, target.Position) <= BulletBombRange;
  56. }
  57. public override BulletType TypeOfBullet => BulletType.AtomBomb;
  58. }
  59. internal sealed class OrdinaryBullet : Bullet // 1倍攻击范围,1倍攻击力,一倍速
  60. {
  61. public OrdinaryBullet(Character player, int radius = GameData.bulletRadius) :
  62. base(player, radius)
  63. {
  64. }
  65. public const double BulletBombRange = GameData.basicBulletBombRange / 6 * 5;
  66. public const double BulletAttackRange = GameData.basicAttackRange / 2;
  67. public override int AP => GameData.basicAp / 6 * 5;
  68. public override int Speed => GameData.basicBulletMoveSpeed / 6 * 5;
  69. public override bool CanAttack(GameObj target)
  70. {
  71. // 圆形攻击范围
  72. return XY.Distance(this.Position, target.Position) <= BulletBombRange;
  73. }
  74. public override BulletType TypeOfBullet => BulletType.OrdinaryBullet;
  75. }
  76. internal sealed class FastBullet : Bullet // 1倍攻击范围,0.2倍攻击力,2倍速
  77. {
  78. public FastBullet(Character player, int radius = GameData.bulletRadius) :
  79. base(player, radius)
  80. {
  81. }
  82. public const double BulletBombRange = GameData.basicBulletBombRange / 4 * 2;
  83. public const double BulletAttackRange = GameData.basicAttackRange;
  84. public override int AP => (int)(0.5 * GameData.basicAp);
  85. public override int Speed => 5 * GameData.basicBulletMoveSpeed / 3;
  86. public override bool CanAttack(GameObj target)
  87. {
  88. // 圆形攻击范围
  89. return XY.Distance(this.Position, target.Position) <= BulletBombRange;
  90. }
  91. public override BulletType TypeOfBullet => BulletType.FastBullet;
  92. }
  93. internal sealed class LineBullet : Bullet // 直线爆炸,宽度1格,长度为2倍爆炸范围
  94. {
  95. public LineBullet(Character player, int radius = GameData.bulletRadius) :
  96. base(player, radius)
  97. {
  98. }
  99. public const double BulletBombRange = GameData.basicBulletBombRange / 3 * 4;
  100. public const double BulletAttackRange = 0.1 * GameData.basicAttackRange;
  101. public override int AP => GameData.basicAp / 3 * 2;
  102. public override int Speed => GameData.basicBulletMoveSpeed / 3;
  103. public override bool CanAttack(GameObj target)
  104. {
  105. double FacingAngle = Math.Atan2(this.FacingDirection.y, this.FacingDirection.x);
  106. if (Math.Abs(FacingAngle - Math.PI / 2) < 1e-2)
  107. {
  108. if (target.Position.y - this.Position.y > BulletBombRange)
  109. return false;
  110. if (target.Position.x < this.Position.x + GameData.numOfPosGridPerCell / 2 && target.Position.x > this.Position.x - GameData.numOfPosGridPerCell / 2)
  111. return true;
  112. return false;
  113. }
  114. else if (Math.Abs(FacingAngle - Math.PI * 3 / 2) < 1e-2)
  115. {
  116. if (target.Position.y - this.Position.y < -BulletBombRange)
  117. return false;
  118. if (target.Position.x < this.Position.x + GameData.numOfPosGridPerCell / 2 && target.Position.x > this.Position.x - GameData.numOfPosGridPerCell / 2)
  119. return true;
  120. return false;
  121. }
  122. else if (Math.Abs(FacingAngle) < 1e-2)
  123. {
  124. if (target.Position.x - this.Position.x > BulletBombRange)
  125. return false;
  126. if (target.Position.y < this.Position.y + GameData.numOfPosGridPerCell / 2 && target.Position.y > this.Position.y - GameData.numOfPosGridPerCell / 2)
  127. return true;
  128. return false;
  129. }
  130. else if (Math.Abs(FacingAngle - Math.PI) < 1e-2)
  131. {
  132. if (target.Position.x - this.Position.x < -BulletBombRange)
  133. return false;
  134. if (target.Position.y < this.Position.y + GameData.numOfPosGridPerCell / 2 && target.Position.y > this.Position.y - GameData.numOfPosGridPerCell / 2)
  135. return true;
  136. return false;
  137. }
  138. double vertical = Math.Tan(FacingAngle + Math.PI / 2);
  139. bool posValue = vertical * Math.Cos(FacingAngle) - Math.Sin(FacingAngle) > 0;
  140. double dist;
  141. dist = vertical * (target.Position.x - this.Position.x) - (target.Position.y - this.Position.y) / Math.Sqrt(1 + vertical * vertical);
  142. if (Math.Abs(dist) > BulletBombRange)
  143. return false;
  144. else if (dist < 0 && posValue) // 位于直线两侧
  145. return false;
  146. vertical = Math.Tan(FacingAngle);
  147. dist = Math.Abs(vertical * (target.Position.x - this.Position.x) - (target.Position.y - this.Position.y)) / Math.Sqrt(1 + vertical * vertical);
  148. if (dist > GameData.numOfPosGridPerCell / 2)
  149. return false;
  150. return true;
  151. }
  152. public override BulletType TypeOfBullet => BulletType.LineBullet;
  153. }
  154. public static class BulletFactory
  155. {
  156. public static Bullet? GetBullet(Character character)
  157. {
  158. Bullet? newBullet = null;
  159. switch (character.BulletOfPlayer)
  160. {
  161. case BulletType.AtomBomb:
  162. newBullet = new AtomBomb(character);
  163. break;
  164. case BulletType.LineBullet:
  165. newBullet = new LineBullet(character);
  166. break;
  167. case BulletType.FastBullet:
  168. newBullet = new FastBullet(character);
  169. break;
  170. case BulletType.OrdinaryBullet:
  171. newBullet = new OrdinaryBullet(character);
  172. break;
  173. default:
  174. break;
  175. }
  176. return newBullet;
  177. }
  178. public static int BulletRadius(BulletType bulletType)
  179. {
  180. switch (bulletType)
  181. {
  182. case BulletType.AtomBomb:
  183. case BulletType.LineBullet:
  184. case BulletType.FastBullet:
  185. case BulletType.OrdinaryBullet:
  186. default:
  187. return GameData.bulletRadius;
  188. }
  189. }
  190. public static double BulletAttackRange(BulletType bulletType)
  191. {
  192. switch (bulletType)
  193. {
  194. case BulletType.AtomBomb:
  195. return AtomBomb.BulletAttackRange;
  196. case BulletType.LineBullet:
  197. return LineBullet.BulletAttackRange;
  198. case BulletType.FastBullet:
  199. return FastBullet.BulletAttackRange;
  200. case BulletType.OrdinaryBullet:
  201. return OrdinaryBullet.BulletAttackRange;
  202. default:
  203. return 0;
  204. }
  205. }
  206. public static double BulletBombRange(BulletType bulletType)
  207. {
  208. switch (bulletType)
  209. {
  210. case BulletType.AtomBomb:
  211. return AtomBomb.BulletBombRange;
  212. case BulletType.LineBullet:
  213. return LineBullet.BulletBombRange;
  214. case BulletType.FastBullet:
  215. return FastBullet.BulletBombRange;
  216. case BulletType.OrdinaryBullet:
  217. return OrdinaryBullet.BulletBombRange;
  218. default:
  219. return 0;
  220. }
  221. }
  222. }
  223. }