import { Component, instantiate, Node, Prefab, tween, Tween, Vec3 } from "cc"; import { BaseLayer } from "../../common/BaseLayer"; import { cocosUtil } from "../../utils/cocosUtil"; import { utilTools } from "../../utils/utilTools"; import { constants } from "../data/constants"; import { localText } from "../data/localText"; import { msgac } from "../data/msgac"; import { RoleItem } from "../item/RoleItem"; import { playerModel } from "../model/playerModel"; import { audioManager } from "./audioManager"; import { designManager } from "./designManager"; import { eventManager } from "./eventManager"; import { resManager } from "./resManager"; import { sdkManager } from "./sdkManager"; import { skillManager } from "./skillManager"; export class levelManager { private static _instance: levelManager; private constructor() { } public static get instance(): levelManager { if (!this._instance) { this._instance = new levelManager(); } return this._instance; } // 关卡内容节点 levelContentLayer: Node; levelLayerComponent: Component; // {floor层数:floorLayer节点} floorLayerObj: any = {}; // 玩家对象 playerRoleItem: RoleItem; // 当前正在打的关卡id level: number = 0; // 当前关卡是否有BOSS levelBoss: boolean = false; // BOSS宝箱是否已拾取 bossBoxHasGet: boolean = false; // 关卡是否已胜利,并且弹出狩猎成功界面 isSuccess: boolean = false; // 是否是跳关胜利 isSkip: boolean = false; // 普通关卡的数量 levelMax: number = 20; // 特殊关卡id数组 levelEspIdArr: number[] = [-1, -2, -3, -4]; // 商店广告增加金币数量 shopAdCoin: number = 500; // 开局神秘商店最小关卡 shopSecretLevelMin: number = 2; // 观看广告直接加的战力值 levelAdAtkAddVal: number = 10; // 金币广告界面增加金币数量 adCoinNum: number = 500; // 装备武器id equipWeaponId: number = 0; // 装备衣服id equipDressId: number = 0; // 行动之前的位置 playerLastPos: Vec3; playerLastGround: Node; // 防止重复点击 canClickGoOn: boolean = true; onClickRoleItem(clickRoleNode: Node) { if (this.playerRoleItem.bodySkeleton.animation != constants.animations.standBy) { return; } let playerNode = this.playerRoleItem.node; let clickRoleItem = clickRoleNode.getComponent(RoleItem); if (clickRoleItem.isPlayer()) { return; } if (!this.canClickGoOn) { return; } clickRoleItem.closeHand(); if (clickRoleItem.hasAd()) { sdkManager.instance.openAd((st: number) => { if (st != 1) { return; } clickRoleItem.hideAd(); this.onClickRoleItem(clickRoleNode); }); return; } this.canClickGoOn = false; let posTarget = cocosUtil.convertToNodeSpace(playerNode, clickRoleItem.getPlayerWorldPos(playerNode)); if (!this.isNeedPlayerMove(clickRoleItem)) { // 不用移动过去 this.moveToClickRoleEnd(clickRoleNode); return; } this.playerLastPos = playerNode.getPosition(); this.playerLastGround = this.playerRoleItem.groundNode; if (this.playerRoleItem.groundNode == clickRoleItem.groundNode) { // 同一个地板 if (playerNode.position.x == posTarget.x && playerNode.position.y == posTarget.y) { // 已在目标位置上 this.moveToClickRoleEnd(clickRoleNode); } else { // 移动过去 if (playerNode.getPosition().x <= posTarget.x) { this.playerRoleItem.setBodyScale(constants.playerBodyScale, constants.playerBodyScale); } else { this.playerRoleItem.setBodyScale(-constants.playerBodyScale, constants.playerBodyScale); } this.playerRoleItem.playAnimation(constants.animations.walk, true); let time = Math.abs(playerNode.getPosition().x - posTarget.x) / constants.playerWalkSpeed; tween(playerNode).to(time, { position: posTarget }).call(() => { this.moveToClickRoleEnd(clickRoleNode); }).start(); } return; } // 不同地板,闪现过去 this.playerRoleItem.startOpenPortal(() => { let bodyNode = this.playerRoleItem.bodyNode; Tween.stopAllByTarget(bodyNode); if (clickRoleItem.isBodyScalePositive()) { bodyNode.setScale(constants.playerBodyScale, constants.playerBodyScale); } else { bodyNode.setScale(-constants.playerBodyScale, constants.playerBodyScale); } playerNode.setPosition(posTarget); this.playerRoleItem.playerAppearFromPortal(() => { this.moveToClickRoleEnd(clickRoleNode); }); }); } moveToClickRoleEnd(clickRoleNode: Node) { let playerNode = this.playerRoleItem.node; let clickRoleItem = clickRoleNode.getComponent(RoleItem); if (this.isNeedPlayerMove(clickRoleItem)) { this.playerRoleItem.floor = clickRoleItem.floor; this.playerRoleItem.groundNode = clickRoleItem.groundNode; } this.playerRoleItem.playAnimation(constants.animations.standBy, true); if (clickRoleItem.isBodyScalePositive()) { this.playerRoleItem.setBodyScale(constants.playerBodyScale, constants.playerBodyScale); } else { this.playerRoleItem.setBodyScale(-constants.playerBodyScale, constants.playerBodyScale); } if (clickRoleItem.roleType == constants.roleItemTypes.monster) { let obj: any = {}; obj.monsterRoleItem = clickRoleItem; eventManager.instance.send(msgac.startFight, obj); return; } if (this.isNeedPlayerMove(clickRoleItem)) { // 镜头跟随 eventManager.instance.send(msgac.adjustPlayerInCenter); } if (clickRoleItem.roleType == constants.roleItemTypes.coinBox) { // 金币宝箱 clickRoleItem.openBoxAward(() => { this.canClickGoOn = true; clickRoleNode.destroy(); let info: any = {}; info.name = constants.layers.AwardGetLayer.name; info.coin = clickRoleItem.coin; info.isBoss = clickRoleItem.isBoss; info.isBox = true; eventManager.instance.send(msgac.openLayer, info); }); return; } if (clickRoleItem.roleType == constants.roleItemTypes.shop) { // 商店 this.canClickGoOn = true; clickRoleNode.destroy(); let info: any = {}; info.name = constants.layers.ShopLayer.name; info.type = clickRoleItem.roleTypeP1; info.id = clickRoleItem.roleTypeP2; eventManager.instance.send(msgac.openLayer, info); return; } if (clickRoleItem.roleType == constants.roleItemTypes.arrow) { // 弓箭 clickRoleItem.playAnimation(constants.animations.animation, false); clickRoleItem.shootArrows(() => { this.canClickGoOn = true; }); return; } if (clickRoleItem.roleType == constants.roleItemTypes.atk) { // 战力倍增 this.canClickGoOn = true; clickRoleNode.destroy(); let atkAddVal = 0; switch (clickRoleItem.roleTypeP1) { case constants.atkChangeTypes.add: atkAddVal = clickRoleItem.atk; break; case constants.atkChangeTypes.multi: atkAddVal = (clickRoleItem.atk - 1) * this.playerRoleItem.atk; break; default: break; } if (atkAddVal > 0) { this.playerRoleItem.addAtk(atkAddVal); } return; } if (clickRoleItem.roleType == constants.roleItemTypes.equip) { // 增加战力 this.canClickGoOn = true; clickRoleNode.destroy(); this.playerRoleItem.addAtk(clickRoleItem.atk); this.addEquip(clickRoleItem.getEquipId()); return; } if (clickRoleItem.roleType == constants.roleItemTypes.skill) { // 获得技能 this.canClickGoOn = true; clickRoleNode.destroy(); playerModel.instance.addSkillNumById(clickRoleItem.roleTypeP1, clickRoleItem.atk); let info: any = {}; info.skillId = clickRoleItem.roleTypeP1; info.num = clickRoleItem.atk; info.pos = cocosUtil.convertToWorldSpace(clickRoleNode); eventManager.instance.send(msgac.skillAdd, info); return; } if (clickRoleItem.roleType == constants.roleItemTypes.dapao) { // 大炮 clickRoleItem.playAnimation(constants.animations.attack, false); clickRoleItem.shootBullets(() => { this.canClickGoOn = true; }); return; } if (clickRoleItem.roleType == constants.roleItemTypes.gunshi) { // 滚石 clickRoleItem.playAnimation(constants.animations.animation, true); clickRoleItem.startGunShi(() => { this.canClickGoOn = true; }); return; } this.canClickGoOn = true; eventManager.instance.send(msgac.showNotice, "未实现的功能"); } // 添加受击特效 addHitEffect(node: Node) { let obj: any = {}; obj.pos = cocosUtil.convertToWorldSpace(node, true); eventManager.instance.send(msgac.showHitEffect, obj); } // 判断一下如果敌人全部阵亡,则弹出狩猎成功的界面,只会弹一次 judgeLevelSuccess() { if (this.isSuccess) { return; } for (let i in this.floorLayerObj) { let floorLayer = this.floorLayerObj[i]; let arr = this.getAllMonsterByFloorLayer(floorLayer); for (let j in arr) { let roleItem = arr[j]; if (!roleItem.isDead()) { // 还有怪物存活,直接返回还未通关 return; } } } if (this.levelBoss && !this.bossBoxHasGet) { // 还未拾取BOSS宝箱 return; } this.isSuccess = true; let obj: any = {}; obj.name = constants.layers.GameContinueLayer.name; obj.nextLayerName = constants.layers.LevelSuccessLayer.name; eventManager.instance.send(msgac.openLayer, obj); } // 刷新玩家形象 refreshPlayerBody() { this.playerRoleItem.bodySkeleton.setSkin(this.getSkinName(this.equipWeaponId, this.equipDressId)); } getSkinName(weaponId: number, dressId: number) { let skinName = ""; if (dressId > 0) { let dressRow = designManager.instance.getRowById(constants.tableName.equip, dressId); skinName = dressRow.skin; } else { skinName = "r1"; } if (weaponId > 0) { let weaponRow = designManager.instance.getRowById(constants.tableName.equip, weaponId); skinName += weaponRow.skin; } else { skinName += "w1"; } return skinName; } // 释放技能 useSkillId(id: number, skillEffectLayer: Node, cb?: Function) { let skill = playerModel.instance.getSkillById(id); let row = designManager.instance.getRowById(constants.tableName.skill, id); if (skill.num <= 0 || !row) { if (cb) { cb(); } return; } // 减少怪物战力 let targetArr = []; let range = 2; let floorStart = this.playerRoleItem.floor - range; if (floorStart < 1) { floorStart = 1; } let floorEnd = this.playerRoleItem.floor + range; for (let i = floorStart; i <= floorEnd; i++) { let floorLayer = this.floorLayerObj[i]; if (!floorLayer) { continue; } let arr = this.getAllMonsterByFloorLayer(floorLayer); targetArr = targetArr.concat(arr); } if (targetArr.length <= 0) { if (cb) { cb(); } eventManager.instance.send(msgac.showNotice, localText.textObj.noMonster); return; } // 播放音效 audioManager.instance.playEffect(row.sound); playerModel.instance.subSkillNumById(id); let tmpArr = []; if (row.target > 0) { let num = row.target; while (num > 0) { num--; let index = Math.floor(Math.random() * targetArr.length); tmpArr.push(targetArr[index]); targetArr.splice(index, 1); if (targetArr.length <= 0) { break; } } } else { tmpArr = targetArr; } // 统计玩家需要增加的战力 let roleAtkAdd = 0; for (let i in tmpArr) { let roleItem = tmpArr[i]; let add = row.atk; if (row.atk > roleItem.atk) { add = roleItem.atk; } roleAtkAdd += add; // 不同技能特效,位置和受击时间点不一样 let pos = cocosUtil.convertToWorldSpace(roleItem.node); let delay = 0; switch (row.body) { case "yunshi": delay = 0.5; pos.y += 40; break; case "ljf": pos.y += 10; break; case "sd": pos.y += 40; break; default: break; } this.levelLayerComponent.scheduleOnce(() => { if (roleAtkAdd > 0) { this.addAtk(roleAtkAdd); roleAtkAdd = 0; } roleItem.addAtk(-row.atk); // 受击动画 roleItem.playAnimation(constants.animations.hit, false, () => { roleItem.playAnimation(constants.animations.standBy, true); }); }, delay); // 显示技能特效 skillManager.instance.showSkillEffect(id, pos, skillEffectLayer, cb); } } // 跳过当前关卡 levelSkip() { // 所有怪物播放死亡动画 this.isSkip = true; let chs = this.levelContentLayer.children; for (let i in chs) { let floorLayer = chs[i]; let arr = this.getAllMonsterByFloorLayer(floorLayer); for (let j in arr) { let roleItem = arr[j]; roleItem.showDeadEffect(); } } } getAllMonsterByFloorLayer(floorLayer: Node) { let arr = []; let groundNodeArr = floorLayer.children; for (let i in groundNodeArr) { let groundNode = groundNodeArr[i]; let roles = groundNode.children; for (let tmp in roles) { let roleNode = roles[tmp]; let roleItem = roleNode.getComponent(RoleItem); if (!roleItem || roleItem.roleType != constants.roleItemTypes.monster) { continue; } if (roleItem.isDead()) { continue; } arr.push(roleItem); } } return arr; } isNeedPlayerMove(clickRoleItem: RoleItem) { if (clickRoleItem.roleType == constants.roleItemTypes.arrow || clickRoleItem.roleType == constants.roleItemTypes.dapao || clickRoleItem.roleType == constants.roleItemTypes.gunshi ) { // 弓箭,大炮,滚石 不用移动过去 return false; } return true; } /** * 获得装备 * 低等级不要覆盖掉高等级装备皮肤 * @param id 装备id */ addEquip(id: number) { let row = designManager.instance.getRowById(constants.tableName.equip, id); let nowLv = 0; if (row.type == constants.equipTypes.weapon) { if (this.equipWeaponId > 0) { nowLv = designManager.instance.getRowById(constants.tableName.equip, this.equipWeaponId).lv; } if (row.lv > nowLv) { this.equipWeaponId = id; // 玩家形象变化 this.refreshPlayerBody(); } } else if (row.type == constants.equipTypes.dress) { if (this.equipDressId > 0) { nowLv = designManager.instance.getRowById(constants.tableName.equip, this.equipDressId).lv; } if (row.lv > nowLv) { this.equipDressId = id; // 玩家形象变化 this.refreshPlayerBody(); } } } // 玩家战力增加 addAtk(val: number) { this.playerRoleItem.addAtk(val); } // 通关后要处理的数据 levelSuccess() { if (!this.isLevelEsp()) { playerModel.instance.setLevel(this.level + 1); this.loadLevelNext(); } } // 计算下一关卡,特殊关卡不作处理 loadLevelNext() { if (this.isLevelEsp()) { return -1; } let next = this.level + 1; if (next > this.levelMax) { // 超过最大关卡数量,随机之前的老关卡 if (next % 10 == 0) { // boss关卡 let num = Math.floor(this.levelMax / 10); let random = Math.floor(Math.random() * num) + 1; next = random * 10; } else { // 普通关卡 let arr = []; for (let i = 1; i <= this.levelMax; i++) { if (i % 10 == 0) { continue; } arr.push(i); } next = utilTools.getRandomItemByArr(arr); } console.log("load random next level:" + next); } console.log("load next level:" + next); playerModel.instance.setLevelAct(next); this.loadLevel(next); return next; } // 是否是特殊关卡 isLevelEsp() { if (this.level < 0) { return true; } return false; } // 是否已打到最大关卡 isLevelMax() { if (playerModel.instance.getLevel() >= this.levelMax) { return true; } return false; } /** * 获取通关后奖励金币数量 * 每10关为boss关卡,奖励比较多 * 特殊关卡奖励另算 */ getLevelSuccessCoin() { if (this.isLevelEsp()) { return 1000; } if (this.level % 10 == 0) { return 500; } return 200; } playerBackLife() { if (this.playerLastPos) { this.playerRoleItem.node.setPosition(this.playerLastPos); } if (this.playerLastGround) { this.playerRoleItem.groundNode = this.playerLastGround; } eventManager.instance.send(msgac.adjustPlayerInCenter); this.playerRoleItem.dead = false; this.playerRoleItem.playerAppearFromPortal(() => { this.playerRoleItem.playAnimation(constants.animations.standBy, true); }); } loadLevel(level: number, onProgress?: Function, onComplete?: Function) { if (level > 0) { // 常规关卡 if (level > this.levelMax) { level = playerModel.instance.getLevelAct(); } } let path = constants.bundles.common.dir.level + "/" + constants.level + level; console.log("load level data:" + level); resManager.instance.loadAsset(constants.bundles.common.name, path, Prefab, onProgress, onComplete); } initLevelLayer(level: number, node: Node, levelLayer: BaseLayer) { this.levelLayerComponent = levelLayer; this.level = level; this.playerRoleItem = null; this.levelContentLayer = node; this.equipWeaponId = playerModel.instance.getEquipWeaponId(); this.equipDressId = playerModel.instance.getEquipDressId(); this.playerLastGround = null; this.playerLastPos = null; this.floorLayerObj = {}; this.levelBoss = false; this.bossBoxHasGet = false; this.isSuccess = false; this.canClickGoOn = true; this.isSkip = false; let floorArr = node.children; let length = floorArr.length; let floor = 0; for (let i = length - 1; i >= 0; i--) { floor++; let floorLayer = floorArr[i]; let groundNodeArr = floorLayer.children; this.floorLayerObj[floor] = floorLayer; for (let j in groundNodeArr) { let groundNode = groundNodeArr[j]; let roles = groundNode.children; for (let tmp in roles) { let roleNode = roles[tmp]; let roleItem = roleNode.getComponent(RoleItem); if (!roleItem) { continue; } if (roleItem.isPlayer()) { // 玩家 this.playerRoleItem = roleItem; this.playerRoleItem.roleTypeP1 = playerModel.instance.getRoleId(); // 暂时不管表里的配置,初始战力以关卡配置为准 // let roleRow = designManager.instance.getRowById(constants.tableName.role, playerModel.instance.getRoleId()); // this.playerRoleItem.atk = roleRow.atk; // this.playerRoleItem.setAtkVal(roleRow.atk); } roleItem.init(groundNode, floor, levelLayer); if (roleItem.roleType == constants.roleItemTypes.monster && roleItem.isBoss) { this.levelBoss = true; } } } } } initRolePlayer(parent: Node) { let pos = cocosUtil.convertToWorldSpace(this.playerRoleItem.node); this.playerRoleItem.node.parent = parent; pos = cocosUtil.convertToNodeSpace(this.playerRoleItem.node, pos); this.playerRoleItem.node.setPosition(pos); this.playerRoleItem.setAtkVal(); this.refreshPlayerBody(); } }