123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- import { _decorator, Node, Vec3, tween, director} from 'cc';
- import { PoolManager } from '../../core/manager/PoolManager';
- import { Game } from '../../game/Game';
- import { uiMgr } from '../../core/manager/UIManager';
- import { Constants } from '../../data/Constants';
- import { GunfightShootUI } from '../../ui/GunfightShootUI';
- import { Bullet2 } from './Bullet2';
- import { GunBase } from '../base/GunBase';
- import { Enemy } from '../../game/Enemy';
- import { Player } from '../../game/Player';
- import { audioMgr } from '../../core/manager/AudioManager';
- const { ccclass, property } = _decorator;
- //玩家所使用的枪 步枪 可以按住镜头一直开枪(M416 AKM)
- @ccclass('Gun2')
- export class Gun2 extends GunBase {
- @property({type: Node,tooltip:"子弹节点"})
- public bulletNode: Node = null!;
- @property({type: Node,tooltip:"开火特效节点"})
- fireEffect: Node = null;
- //枪的拥有者
- public holder: Player|Enemy = null;
- //开枪结束回调
- public endCb: Function = null!;
- //换弹匣的回调
- public ammoCb: Function = null;
- //触发间隔时间统计
- private curTime: number = 0;
- //所有的烟雾
- public smokes: Array<Node> = []!
-
- onLoad() {
- this.bulletNode.active = false;
- this.muzzleNode.active = false;
- }
- /**
- * 设置枪的数据
- * @param data 枪的数据
- * @param endCB 结束回调
- * @param ammoCb 换弹匣回调
- */
- public init(data: any,holder: any,endCb?: Function,ammoCb?: Function){
- this.data = data;
- this.shotBullets = 0;
- this.isFire = false;
- this.holder = holder;
- this.endCb = endCb;
- this.ammoCb = ammoCb;
- }
- //开火
- public fire() {
- this.isFire = true;
- this.curTime = 0.0;
- }
- //结束开火
- public endFire(){
- this.isFire = false;
- this.endCb?.(this.data);
- this.recycle();
- }
- /**
- * 直接开抢射杀敌人
- */
- public killEnemy(e: Enemy){
- if(e.isDead
- ||Game.I.isPause){
- return;
- }
- const destPos: Vec3 = e.node.worldPosition.clone();
- const bullet: Bullet2 = this.getBulleNode();
- bullet.init(this,true);
- tween(bullet.node)
- .to(0.3, {worldPosition:destPos})
- .call(() => {
- bullet.isDead = true;
- PoolManager.putNode(bullet.node);
- //直接打死 最大血量乘以2倍
- e.subHP(e.data.hp * 2,this.data);
- })
- .start();
- }
- /**
- * 展示子弹
- */
- public createBullet() {
- if(!this.holder
- ||this.holder.isDead
- ||!this.isFire
- ||Game.I.isPause
- ||Game.I.isGameOver){
- return;
- }
- audioMgr.playOneShot(this.data.gun_sound);
- this.playParticle(this.fireEffect);
- this.getBulleNode();
- this.shotBullets ++;
- //换弹夹的操作
- if(this.shotBullets >= this.data.magazine){
- this.shotBullets = 0;
- this.ammoCb?.(this.data);
- }
- }
- /**
- * 初始化一个子弹
- * @param isGuaranteedHit 子弹是否必中(必中的时候targetNode不能为空)
- * @param targetNode 射击的目标对象
- * @returns 返回一颗子弹
- */
- public getBulleNode(isGuaranteedHit: boolean = true, targetNode: Node = null): Bullet2{
- //从对象池获取子弹节点
- const bulletNode: Node = PoolManager.getNode(this.bulletNode, director.getScene());
- const bullet: Bullet2 = bulletNode.getComponent(Bullet2);
- bullet.init(this);
- bulletNode.worldPosition = this.muzzleNode.worldPosition.clone();
- //计算基准方向(瞄准目标或准星位置)
- const shootUI:GunfightShootUI = uiMgr.getPageComponent(Constants.popUIs.gunfightShootUI);
- const targetPos = targetNode ? targetNode.worldPosition : shootUI.getCrossHairPos();
- const baseDirection = Vec3.subtract(new Vec3(), targetPos, this.muzzleNode.worldPosition).normalize();
- //最终弹道方向
- let finalDirection: Vec3;
- if(isGuaranteedHit) {//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);
- return bullet;
- }
- //激活调用 持续开火
- protected update(dt: number): void {
- let player: Player = Game.I.player;
- if(!player
- ||player.isDead
- ||!this.isFire
- ||Game.I.isPause
- ||Game.I.isGameOver){
- return;
- }
- if(Game.I.player.isReloadMagazine){
- return;
- }
- if(!Game.I.player.shootUI.isScopeOpen){
- this.endFire();
- return;
- }
- //每0.4秒攻击一次 发射一颗子弹
- this.curTime += dt;
- if(this.curTime >= 0.2) {
- //播放射击帧动画
- this.createBullet();
- this.curTime = 0;
- }
- }
- /**
- * 回收烟雾
- */
- public recycle(){
- this.smokes.forEach(e => {
- if(e && e.parent){
- PoolManager.putNode(e);
- }
- });
- this.smokes = [];
- }
- }
|