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

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