Bullet1.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import { _decorator, Vec3,Node, geometry, PhysicsSystem, PhysicsRayResult} from 'cc';
  2. import { Game } from '../../game/Game';
  3. import { GunBase } from '../base/GunBase';
  4. import { BulletBase } from '../base/BulletBase';
  5. import { PoolManager } from '../../core/manager/PoolManager';
  6. import { Sundries } from '../../game/Sundries';
  7. import { Enemy } from '../../game/Enemy';
  8. import { GameEnums } from '../../data/GameEnums';
  9. import { GunAttribute, userIns } from '../../data/UserData';
  10. const { ccclass, property } = _decorator;
  11. //玩家所用子弹 98k m24 awm BarrettM82A1 重狙子弹
  12. @ccclass('Bullet1')
  13. export class Bullet1 extends BulletBase {
  14. //是否必死 必死的子弹不会回收 要自己控制
  15. private isRemoveDead: boolean = false;
  16. //射击方向的位置
  17. private vector: Vec3 = null;
  18. //计算子弹停留时间
  19. private time: number = 0.6;
  20. /**
  21. * 初始化一个子弹
  22. */
  23. /**
  24. * 初始化一个子弹
  25. * @param gun 属于哪把枪
  26. * @param isRemoveDead 是否不受控制的子弹自己管理
  27. */
  28. public init(gun:GunBase,isRemoveDead:boolean = true){
  29. this.gunBase = gun;
  30. this.isDead = false;
  31. this.isRemoveDead = isRemoveDead;
  32. }
  33. /**
  34. * 设置子弹开始位置和射击方向
  35. * @param v 射向的方向
  36. */
  37. public setBulletVector(v: Vec3){
  38. this.time = this.getBulletTime();
  39. const bulletSpeed = this.gunBase.data.bulletSpeed / 3;
  40. this.vector = v.clone().multiplyScalar(bulletSpeed);
  41. this.node.forward = v;
  42. }
  43. /**
  44. * 射击速度发生改变
  45. */
  46. public speedChange() {
  47. const bulletSpeed = this.gunBase.data.bulletSpeed;
  48. if(this.vector) {
  49. this.vector = this.vector.normalize().multiplyScalar(bulletSpeed);
  50. }
  51. }
  52. /**
  53. * 实时帧更新
  54. */
  55. public update(deltaTime: number) {
  56. if(Game.I.isGameOver
  57. || Game.I.isPause) {
  58. this.isDead = true;
  59. PoolManager.putNode(this.node);
  60. return;
  61. }
  62. if(this.vector) {
  63. const moveDelta = this.vector.clone().multiplyScalar(deltaTime);
  64. this.node.worldPosition = this.node.worldPosition.add(moveDelta);
  65. //开始检测射击
  66. this.scheduleOnce(this.rayPreCheck,this.time);
  67. }
  68. }
  69. /**
  70. * 检测射击
  71. * @param b
  72. * @param len 检测
  73. */
  74. private rayPreCheck() {
  75. let screenPos: Vec3 = this.stabilityGetBulletPos(400);
  76. const r = geometry.Ray.create();
  77. Game.I.camera.screenPointToRay(screenPos.x, screenPos.y, r);
  78. const hasHit = PhysicsSystem.instance.raycast(r, 0xffffffff, 100000, true);
  79. const raycastResults:PhysicsRayResult[] = PhysicsSystem.instance.raycastResults;
  80. if(hasHit && raycastResults.length > 0){
  81. const gunPos = this.gunBase.node.worldPosition;
  82. raycastResults.sort((a, b) => {
  83. const aDist = Vec3.distance(a.hitPoint, gunPos);
  84. const bDist = Vec3.distance(b.hitPoint, gunPos);
  85. return aDist - bDist;
  86. });
  87. //先查找 要检测的物体 对象上带args参数的就是优先检测的
  88. let targetResult: PhysicsRayResult | null = null;
  89. for (const result of raycastResults) {
  90. if (result.collider["args"]) {
  91. targetResult = result;
  92. break;
  93. }
  94. }
  95. targetResult = targetResult ?? raycastResults[0];
  96. this.addHitImpact(targetResult);
  97. const args:any = targetResult.collider["args"];
  98. if(args){
  99. let [type,cls] = args;
  100. let attack: number = this.gunBase.data.attack;
  101. if(cls instanceof Enemy){
  102. const e: Enemy = cls as Enemy;
  103. //爆头击杀
  104. let isHeadShot:boolean = false;
  105. if(type == GameEnums.enemyPartType.head){
  106. Game.I.player.headShotNum += 1;
  107. attack = Game.I.player.pData.headshotDmgMul * attack;
  108. isHeadShot = true;
  109. }
  110. //打到了盾兵上的盾
  111. if(type == GameEnums.enemyPartType.shield
  112. && e.shieldHp > 0){
  113. e.shieldHp -= attack;
  114. return;
  115. }
  116. e.isShotHead = isHeadShot;
  117. //坦克是单独的碰撞体
  118. if(e.isTank()){
  119. if(type == GameEnums.enemyPartType.tank){
  120. e.subHP(attack,this.gunBase.data);
  121. }
  122. }else{
  123. e.raycastResults = targetResult;
  124. e.subHP(attack,this.gunBase.data);
  125. }
  126. }else if(cls instanceof Sundries){
  127. const sundrie: Sundries = cls as Sundries;
  128. sundrie.subHP(attack,this.gunBase.data,Game.I.player.node);
  129. }
  130. }
  131. //自动回收了子弹
  132. this.autoRecycle();
  133. }
  134. }
  135. }