import { _decorator, Component, Node, Prefab, instantiate, Vec3, UITransform, EventHandler, tween, math, UIOpacity, Label, } from 'cc'; import { ResourcesUtils } from '../../core/resourceManager/ResourcesUtils'; import { Sound } from '../../core/sound/Sound'; import { WindowManager } from '../../core/ui/window/WindowManager'; import { WindowOpenMode } from '../../core/ui/window/WindowOpenMode'; import { g } from '../../Data/g'; import { LoginWaitWin } from '../../Windows/LoginWaitWin'; import { BattleRedPacketWindow } from './BattleRedPacketWindow'; import { BattleRole, BattleRoleState } from './BattleRole'; const { ccclass, property } = _decorator; /**战斗控制器 */ @ccclass('BattleController') export class BattleController extends Component { @property({ tooltip: "神将资源路径" }) public battleRolePrefabPath = ''; @property({ tooltip: "特效资源路径" }) public battleEffectPrefabPath = ''; @property({ type: EventHandler, tooltip: "对战结束" }) battleOverHanedler: EventHandler; @property({ type: Node, tooltip: "战斗位置区域" }) battleNode: Node; @property({ type: Label, tooltip: "我方队伍人数文本" }) ourNumLabel: Label; @property({ type: Label, tooltip: "敌方队伍人数文本" }) enemyNumLabel: Label; @property({ type: Node, tooltip: "跳过" }) skipNode: Node; /**我方战斗神将 */ private ourGenerals: Array = []; /**敌方方战斗神将 */ private enemyGenerals: Array = []; /*攻击数据 */ private attackList = []; /**距离战斗点的长度 */ private battleSpacing = 100; /**距离战斗点的长度 */ private battleBackSpacting = 125; private initX = [0, -130, 130, -260, 260]; private initY = -1000;//我方 private col_num = 5;//列数 private ourMaxHP: number = 0; private enemyMaxHp: number = 0; private startTime = 0; private checkTime = 2000; private startCheck = false; private isOver = false; start() { this.isOver = false; this.isFirst = true; let enemyNum = (g.battleData.enemyFriendDatas.length + g.battleData.enemyGenerals.length); enemyNum = enemyNum || 1; this.enemyNumLabel.string = enemyNum + '人'; let ourNum = g.battleData.ourBattleGenerals.length; ourNum = ourNum || 1; this.ourNumLabel.string = ourNum + '人'; } public async setData(data: any) { this.skipNode.active = true; this.ourGenerals = []; this.enemyGenerals = []; this.createOurGenerals(); } update() { if (this.startCheck && this.startTime < Date.now()) { this.startTime = Date.now() + this.checkTime; this.checkBattle(); } } /** * 创建战斗神将 */ private async createOurGenerals() { let _window = await WindowManager.open("Prefabs/Windows/加载等待窗口", WindowOpenMode.NotCloseAndCover); //敌方神将 for (let i = g.battleData.enemyBattleGenerals.length - 1, j = 0; i >= 0; i--) { let preFabsData = await ResourcesUtils.load(this.battleRolePrefabPath, Prefab, this.node); var generalNode = instantiate(preFabsData); let general = generalNode.getComponent(BattleRole); general.name = "name" + i; general.isPlayAaimation = false; generalNode.parent = this.node; generalNode.position = new Vec3(this.initX[j], Math.abs(this.initY - Math.random() * 300), 0); general.setData(g.battleData.enemyBattleGenerals[i], BattleRoleState.Fight, false); j = ++j == 5 ? 0 : j; this.enemyMaxHp += general.HP; this.enemyGenerals.push(general); // break; } //我方神将 for (let i = 0, j = 0; i < g.battleData.ourBattleGenerals.length; i++) { let preFabsData = await ResourcesUtils.load(this.battleRolePrefabPath, Prefab, this.node); var generalNode = instantiate(preFabsData); let general = generalNode.getComponent(BattleRole); general.isPlayAaimation = false; general.name = "name" + i; generalNode.parent = this.node; generalNode.position = new Vec3(this.initX[j], this.initY - Math.random() * 300, 0); general.setData(g.battleData.ourBattleGenerals[i], BattleRoleState.Fight); j = ++j == 5 ? 0 : j; this.ourMaxHP += general.HP; this.ourGenerals.push(general); // break; } _window.getComponent(LoginWaitWin).close();//关闭加载等待界面 // this.startCheck = true; // this.battleStart(); this.checkBattle(); } private isFirst = true; /**距离检测战斗 */ private checkBattle() { if (this.isOver) { return; } if (!this.ourGenerals.length || !this.enemyGenerals.length) { this.battleOver(); return; } this.enemyGenerals.length > this.ourGenerals.length ? this.ourGenerals.length : this.enemyGenerals.length; let len = this.enemyGenerals.length > this.ourGenerals.length ? this.ourGenerals.length : this.enemyGenerals.length; for (let i = 0; i < len; i++) { let distance = Vec3.distance(this.enemyGenerals[i].node.position, this.ourGenerals[i].node.position);//距离 let newPos = this.getBattlePosition(this.enemyGenerals[i].node.position, this.ourGenerals[i].node.position, this.enemyGenerals[i].speed / (this.ourGenerals[i].speed + this.enemyGenerals[i].speed)); let distance1 = Vec3.distance(this.enemyGenerals[i].node.position, newPos[0]);//距离 let distance2 = Vec3.distance(this.ourGenerals[i].node.position, newPos[0]);//距离 let attackDelay = Math.random() * 0.3; this.setAttackData(attackDelay, false, this.enemyGenerals[i], this.ourGenerals[i].generalBaseData.attack, distance1 / this.enemyGenerals[i].speed, newPos[1], newPos[0], newPos[3]); this.setAttackData(attackDelay, true, this.ourGenerals[i], this.enemyGenerals[i].generalBaseData.attack, distance2 / this.ourGenerals[i].speed, newPos[2], newPos[0], newPos[4]); } if (this.enemyGenerals.length > this.ourGenerals.length) { for (let i = len; i < this.enemyGenerals.length; i++) { if (this.enemyGenerals[i].showState == BattleRoleState.Fight) { this.move(this.enemyGenerals[i], this.getBattleWaitPosition()); } } } else { for (let i = len; i < this.ourGenerals.length; i++) { if (this.ourGenerals[i].showState == BattleRoleState.Fight) { this.move(this.ourGenerals[i], this.getBattleWaitPosition()); } } } this.playAttack(); } private setAttackData(attackDelay: number, showEffect: boolean, battleRole: BattleRole, attack: number, duration: number, tagretPos: Vec3, battlePos: Vec3, battleBack: Vec3) { this.attackList.push({ attackDelay, showEffect, general: battleRole, attack: attack, duration: duration, tagretPos: tagretPos, battlePos: battlePos, battleBack: battleBack }); } private playAttack() { let i = 0; while (i < this.attackList.length) { // console.log(this.attackList[i].general.node.position); this.attackList[i].general.node.setSiblingIndex(this.node.children.length - 1); this.moveGeneral(this.attackList[i].attackDelay, this.attackList[i].showEffect, this.attackList[i].general, this.attackList[i].attack, this.attackList[i].duration, this.attackList[i].tagretPos, this.attackList[i].battlePos, this.attackList[i].battleBack); this.attackList.splice(0, 1); } } /*移动初始位置 */ private moveGeneral(attackDelay: number, showEffect: boolean, battleRole: BattleRole, attack: number, duration: number, tagretPos: Vec3, battlePos: Vec3, battleBack: Vec3) { tween(battleRole.node).to(duration, { position: tagretPos }).call(() => { this.attack(attackDelay, showEffect, battleRole, attack, battlePos, battleBack); }).start(); } public attack(attackDelay: number, showEffect: boolean, general: BattleRole, attack: number, v1: Vec3, v3: Vec3) { if (this.isOver) { return; } let nowPostion = general.node.position.clone(); tween(general.node). to(attackDelay, { position: v3 }, { easing: "sineOut" }). call(() => { showEffect && this.playAttackSoundAndEffect(v1); }). to(0.15, { position: v1 }, { easing: "sineOut" }). to(0.2, { position: v3 }, { easing: "sineIn" }). to(0.05, { position: nowPostion }, { easing: "sineIn" }).call(() => { this.attackFinish(general, attack); }).start(); } private myGeneralNum = 0; public attackFinish(general: BattleRole, attack: number) { if (this.isOver) { return; } general.setHp(attack); if (general.HP <= 0) {//delete 死亡 general.HP = 0; if (this.ourGenerals.indexOf(general) != -1) { this.ourGenerals.splice(this.ourGenerals.indexOf(general), 1); } if (this.enemyGenerals.indexOf(general) != -1) { this.enemyGenerals.splice(this.enemyGenerals.indexOf(general), 1); } this.enemyNumLabel.string = this.enemyGenerals.length + '人'; if (!this.ourGenerals.length && !this.enemyGenerals.length) { this.ourNumLabel.string = (this.ourGenerals.length == this.ourMaxHP ? 0 : 1) + '人'; this.myGeneralNum = 1; return; } this.ourNumLabel.string = this.ourGenerals.length + '人'; tween(general.node.getComponent(UIOpacity)).to(0.3, { opacity: 0 }).call(() => { general.node.active = false; }).start(); } } //播放战斗光效和声音 private async playAttackSoundAndEffect(point: Vec3) { let effect = await ResourcesUtils.load(this.battleEffectPrefabPath, null, this.node); let effectNode = instantiate(effect); effectNode.parent = this.node; effectNode.setPosition(point); if (this.isFirst) { this.startTime = Date.now() + this.checkTime - 1000; this.isFirst = false; this.startCheck = true; } // this.attactSound.play(); } /**没有攻击目标神将移动*/ private move(general: BattleRole, point: Vec3) { tween(general.node).to(Math.random() * 5 + (Vec3.distance(general.node.position, point) / general.speed), { position: point }).call(() => { general.battleState = BattleRoleState.Move; }).start(); } private onJump() { this.battleOver(true); } private battleOver(isJump: boolean = false) { if (this.isOver) { return; } this.isOver = true; if (isJump) { g.battleData.isWin = this.ourMaxHP >= this.enemyMaxHp;//谁血多谁赢 } else { if (this.ourGenerals.length != this.enemyGenerals.length) { g.battleData.isWin = this.ourGenerals.length > this.enemyGenerals.length; } else { if (this.myGeneralNum) { g.battleData.isWin = true; this.myGeneralNum = 0; } else { g.battleData.isWin = this.ourMaxHP >= this.enemyMaxHp;//谁血多谁赢 } } } this.skipNode.active = false; this.startCheck = false; for (let i = 0; i < this.ourGenerals.length; i++) { this.ourGenerals[i].battleState = BattleRoleState.Fight; } for (let i = 0; i < this.enemyGenerals.length; i++) { this.enemyGenerals[i].battleState = BattleRoleState.Fight; } this.enemyGenerals = []; this.ourGenerals = []; this.battleOverHanedler.emit([]);//战斗结束 } /**战斗坐标计算 */ private getBattlePosition(point1: Vec3, point2: Vec3, point1_ratio: number) { let w = point1.x > point2.x ? point1.x - point2.x : point2.x - point1.x; let h = point1.y > point2.y ? point1.y - point2.y : point2.y - point1.y; let newx = point1.x > point2.x ? point1.x - w * point1_ratio : point2.x - w * (1 - point1_ratio); let newy = point1.y > point2.y ? point1.y - h * point1_ratio : point2.y - h * (1 - point1_ratio); let battlePoint = new Vec3(newx, newy, 0);//战斗位置 // console.log(battlePoint); let ration = Math.sqrt(this.battleSpacing * this.battleSpacing / (w * w + h * h));//神将位置比 let ww = ration * w; let hh = ration * h; let point1Battle = new Vec3(newx + ww, newy + hh, 0);//神将位置1 let point2Battle = new Vec3(newx - ww, newy - hh, 0);//神将位置2 let ration1 = Math.sqrt(this.battleBackSpacting * this.battleBackSpacting / (w * w + h * h));//第一个神将战斗后退位置比 let www = ration1 * w; let hhh = ration1 * h; let point1Back = new Vec3(newx + www, newy + hhh, 0);//神将战斗后退位置1 let point2Back = new Vec3(newx - www, newy - hhh, 0);//神将战斗后退位置2 //战斗占, 敌方点,我方点 return [battlePoint, point1Battle, point2Battle, point1Back, point2Back]; } /** */ private getBattleWaitPosition() { let targetIndex = Math.floor(Math.random() * 5); let targetX = (Math.random() > 0.5 ? +Math.random() * 200 : -Math.random() * 200); let targetY = (Math.random() > 0.5 ? +Math.random() * 200 : -Math.random() * 200); return new Vec3(targetX, targetY, 0); } }