import { _decorator, Animation, Component, macro, Node, Sprite, SpriteFrame, Vec2, Vec3 } from 'cc'; import { TowerData } from '../DataItem/ItemData'; import { resMgr } from '../Frames/ResourcesMgr'; import { GameMgr } from './GameFrameWork/GameMgr'; import { MapMgr } from './GameFrameWork/MapMgr'; import { TowerUI } from './GameFrameWork/TowerUI'; import { BulletMgr } from './GameFrameWork/BulletMgr'; import { MonsterMgr } from './GameFrameWork/MonsterMgr'; import { Tools } from './Tools/Tools'; const { ccclass, property } = _decorator; @ccclass('Tower') export class Tower extends Component { private _tilePos: Vec2 = null; private _atkRadiums: number = 0; private _lv: number = 1; private _atkTarget: Node = null; //炮 protected _gun: Node = null; //地盘 protected _chassis: Node = null; //塔的数据 protected _data: TowerData = null; protected _isFire: boolean = false; //保存面向攻击对象的旋转角度 protected _targetAngle: number = 0; //子弹的动画精灵帧的数组 protected _bulletFrames: SpriteFrame[] = []; //自己的动画的精灵帧 protected _aniFrames: SpriteFrame[] = []; //动画组件 protected _ani: Animation = null; protected onLoad(): void { this._gun = this.node.getChildByName("Gun"); this._chassis = this.node.getChildByName("Chassis"); } protected setAni(){ for(let i = 1; i <= this._data.fireAniCount; i++){ this._aniFrames.push(resMgr.getSpriteFrame(this._data.fireAniImg + this._lv + i)); } this._ani = Tools.createAnimation(this._aniFrames, 20, this._gun); } init(data: TowerData, pos: Vec3) { this._data = data; //子弹动画精灵帧 for(let i = 1; i <= data.bulletAniCount; i++){ this._bulletFrames.push(resMgr.getSpriteFrame(data.bulletAniImg + this._lv + i)); } this._atkRadiums = data.atkRadiums[this._lv - 1]; const frame = resMgr.getSpriteFrame(data.chassis[0]); this._chassis.getComponent(Sprite).spriteFrame = frame; this.node.setPosition(pos); //炮的图片 this._gun.getComponent(Sprite).spriteFrame = resMgr.getSpriteFrame(data.fireAniImg + this._lv + "1"); this._tilePos = GameMgr.Instance.getModuler(MapMgr).getTiledByPos(new Vec2(pos.x, pos.y)); } protected _attack(){ //一定不要写代码 只是为了产生多态 其实是一个接口 实现不同的派生类的方法 } protected stopAttack(){ } //开火 protected _fire(){ this._isFire = true; this._attack(); } protected _unFire(){ //this.unscheduleAllCallbacks(); this._isFire = false; this.stopAttack(); } bTouch(pos: Vec2): boolean { const tiled = GameMgr.Instance.getModuler(MapMgr).getTiledByPos(new Vec2(pos.x, pos.y)); if (this._tilePos.equals(tiled)) { this.showUI(); return true; }; return false; } showUI() { GameMgr.Instance.getModuler(TowerUI).show(this.node.position) } protected update(dt: number): void { if(this._atkTarget){ //旋转角度 const vec: Vec3 = this._getVec(this._atkTarget).normalize(); let angle = Vec3.angle(new Vec3(0, 1), vec); if(vec.x > 0){ angle *= -1; } //this.unscheduleAllCallbacks(); //弧度转角度 this._targetAngle = angle / Math.PI * 180; if(this._data.rotate){ this._gun.angle = this._targetAngle; } } if(this._isFire){ //已经锁定的目标 是否死亡(销毁) 是否走出攻击范围 const dis = this._getVec(this._atkTarget).length(); if(dis > this._atkRadiums){ this._atkTarget = null; this._unFire(); } return; } if(this._findMonster()){ this._fire(); } } private _findMonster(){ const monsters: Node[] = GameMgr.Instance.getModuler(MonsterMgr).node.children; for(const node of monsters){ //计算node和自己的距离 const dis: number = this._getVec(node).length(); if(dis <= this._atkRadiums){ this._atkTarget = node; return true; //this._fire(); } } return false; } protected _getVec(node: Node): Vec3{ return node.position.clone().subtract(this.node.position); } }