123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- import { _decorator, Node, Vec3, director} from 'cc';
- import { PoolManager } from '../../core/manager/PoolManager';
- import { Game } from '../../game/Game';
- import { GunBase } from '../base/GunBase';
- import { Bullet14 } from './Bullet14';
- import { Utils } from '../../utils/Utils';
- import { Enemy } from '../../game/Enemy';
- import { Player } from '../../game/Player';
- import { audioMgr } from '../../core/manager/AudioManager';
- import { Constants } from '../../data/Constants';
- const { ccclass, property } = _decorator;
- //1006 坦克
- @ccclass('Gun14')
- export class Gun14 extends GunBase {
- @property({type: Node,tooltip:"子弹节点"})
- public bulletNode: Node = null!;
- @property({type: Node,tooltip:"开火特效节点"})
- fireEffect: Node = null;
- private isCb: boolean = false;
- //枪的拥有者
- public enemy: Enemy = null;
- //开枪结束回调
- public endCb: Function = null!;
- //换弹匣的回调
- public ammoCb: Function = null;
- //触发间隔时间统计
- private curTime: number = 0;
- //是否是第一次开火
- private isFristShot: boolean = false;
- //所有的烟雾
- public smokes: Array<Node> = []!
- //是否是第一次激活开枪
- public isFristShoot: boolean = false;
- //为了戳开子弹产生的时间间隔统计
- public diff: number = 0;
- //随机延迟的时间
- public r_delay: number = 0;
- //继续正常统计时间
- public isGo: boolean = true;
- onLoad() {
- this.bulletNode.active = false;
- this.muzzleNode.active = false;
- }
- /**
- * 设置枪的数据
- * @param data 枪的数据
- * @param endCB 结束回调
- * @param ammoCb 换弹匣回调
- */
- public init(data: any,enemy: any,endCb?: Function,ammoCb?: Function){
- this.data = data;
- this.curTime = 0;
- this.isFire = false;
- this.isFristShot = true;
- this.enemy = enemy;
- this.endCb = endCb;
- this.ammoCb = ammoCb;
- this.node.eulerAngles = new Vec3(0, 180, 0);
- }
- //开火
- public fire() {
- this.isFire = true;
- this.playParticle(this.fireEffect);
- }
- //结束开火
- public endFire(){
- this.isFire = false;
- this.endCb?.(this.data);
- this.recycle();
- }
- /**
- * 展示子弹
- */
- public createBullet() {
- if(!this.getNextAllow())return;
- let delay: number = 0.1;
- for(let i = 0; i < this.data.bullet_number; i++){
- this.scheduleOnce((k: number)=>{
- delay += Utils.getRandomFloat(0,0.2);
- if(!this.getNextAllow())return;
- //获取射击的精准度
- const isHit: boolean = this.enemy.calculateIsHit();
- //创建子弹
- this.getBulleNode(isHit);
- },delay * i);
- }
- }
- /**
- * 初始化一个子弹
- * @param isGuaranteedHit 子弹是否必中
- * @returns 返回一颗子弹
- */
- public getBulleNode(isHit: boolean = true): Bullet14{
- //从对象池获取子弹节点
- const bulletNode: Node = PoolManager.getNode(this.bulletNode, director.getScene());
- const bullet: Bullet14 = bulletNode.getComponent(Bullet14);
- bullet.init(this);
- bulletNode.setWorldPosition(this.muzzleNode.worldPosition);
- let playPos: Vec3 = Game.I.player.head.worldPosition.clone();
- const baseDirection = Vec3.subtract(new Vec3(), playPos,this.muzzleNode.worldPosition).normalize();
- //最终弹道方向
- let finalDirection: Vec3;
- if(isHit) {//100%必中(无偏移)
- finalDirection = baseDirection;
- }else{//非必中:在基准方向上添加小范围随机偏移
- const maxOffsetAngle = 5;
- const offsetX = (Math.random() - 0.5) * maxOffsetAngle * Math.PI / 180;
- const offsetY = (Math.random() - 0.5) * maxOffsetAngle * Math.PI / 180;
- //应用偏移(保持Z轴主要方向)
- finalDirection = new Vec3(
- baseDirection.x + offsetX,
- baseDirection.y + offsetY,
- baseDirection.z // 保持主要前进方向
- ).normalize();
- }
- //设置子弹方向
- bulletNode.forward = finalDirection;
- bullet.setBulletVector(finalDirection,isHit);
- return bullet;
- }
- //激活调用 持续开火
- protected update(dt: number): void {
- if(!this.getNextAllow())return;
- //每几秒攻击一次
- let m: number = this.data.atk_speed;
- //不是第一次激活 有延迟间隔
- if(!this.isFristShoot){
- m = this.isFristShoot ? 0 : m;
- if(this.diff >= this.r_delay && !this.isGo){
- this.diff += dt;
- this.isGo = true;
- return;
- }else{
- this.curTime += dt;
- }
- }else{//第一次激活 就直接开枪不延迟
- m = this.isFristShoot ? 0 : m;
- }
- //在随机延迟的时间间隔里 发射一颗子弹
- if(this.curTime >= m - this.r_delay) {
- if(this.isFire){
- this.isFristShoot = false;
- this.r_delay = Utils.getRandomFloat(0.4,0.8);
- this.diff = 0;
- this.isGo = false;
- audioMgr.playOneShot(Constants.audios.Tank_Attack,false);
- this.createBullet();
- this.curTime = 0;
- this.isCb = false;
- }else{
- if(!this.isFire && !this.isCb){
- this.isFire = false;
- this.endCb?.(this.data.type);
- this.isCb = true;
- }
- }
- }
- }
- /**
- * 是否可以允许操作
- */
- private getNextAllow(){
- let player: Player = Game.I.player;
- if(!player
- ||player.isDead
- ||!this.isFire
- ||Game.I.isPause
- ||Game.I.isGameOver){
- return false;
- }
- return true;
- }
- /**
- * 回收烟雾
- */
- public recycle(){
- this.smokes.forEach(e => {
- if(e && e.parent){
- PoolManager.putNode(e);
- }
- });
- this.smokes = [];
- }
- }
|