import SKUIUtil from "../ts/gear_2.3.4/util/SKUIUtil"; import GameModel from "../ts/core/GameModel"; import MyModel from "../ts/core/MyModel"; import AudioUtil from "../ts/core/AudioUtil"; import SKDataUtil from "../ts/gear_2.3.4/util/SKDataUtil"; import Report from "../ts/gear_2.3.4/net/Report"; import GameUtil from "../ts/core/GameUtil"; import SKLogger from "../ts/gear_2.3.4/util/SKLogger"; import GangWar from "../ts/GangWar"; let GameRes = require('./GameRes'); let CNpcMgr = require('./NpcMgr'); cc.Class({ extends: cc.Component, properties: { roleNode: cc.Node, homePre: cc.Prefab, transferPre: cc.Prefab, touchPre: cc.Prefab, rolepre: cc.Prefab, effPre: cc.Prefab, gateRight: cc.Node, gateLeft: cc.Node, }, ctor() { this.loaded = false; this.MAP_RES_WIDTH = 5258; this.MAP_RES_HEIGHT = 2910; this.gridWidth = 20; this.gridHeight = 20; this.mapNodeSize = 512; this.rowCount = Math.ceil(this.MAP_RES_HEIGHT / this.gridHeight); this.lineCount = Math.ceil(this.MAP_RES_WIDTH / this.gridWidth); this.borderCount = 1; //屏幕外的圖片顯示寬度 this.transferList = []; this.mapNodeArr = []; this.mapId = 0; this.mapres = 0; this.lastpos = { x: 0, y: 0 }; }, onLoad() { this.canvasWidht = cc.find('Canvas').width; this.canvasHeight = cc.find('Canvas').height; // this.canvasWidht = 1024; // this.canvasHeight = 576; this.gamelogic = cc.find('Canvas').getComponent('GameLogic'); }, start() { this.roleNode.zIndex = 3; this.myRole = this.roleNode.getComponent('role'); this.myRole.isMy = true; this.myRole.setInfo(GameModel.player, 1); MyModel.shared.horseList = this.myRole.horseList; GameModel.player.setNode(this.roleNode); this.loadMap(false); if (!this.loaded) { this.loaded = true; this.gamelogic.loadComplete(); } }, changeMap(mapid, pos, issend = true) { console.warn("換地圖", mapid) if (GameModel.player.teamid > 0 && (!GameModel.player.tempLeave && !GameModel.player.isleader) && issend) { return; } if (GameModel.player.mapid == mapid) { return; } this.myRole.actlist = []; this.roleNode.stopAllActions(); this.myRole.living_state = 0; GameModel.player.mapid = mapid; // this.unschedule(this.checkRolePos); cc.sys.garbageCollect(); this.loadMap(true, pos); if (issend) { GameModel.send('c2s_change_map', { accountid: GameModel.player.accountid, roleId: GameModel.player.roleid, mapid: mapid, x: this.myRole.netInfo.x, y: this.myRole.netInfo.y }); } }, changeMapXY(mapid, pos, issend = true) { if (GameModel.player.teamid > 0 && (!GameModel.player.tempLeave && !GameModel.player.isleader) && issend) { return; } this.myRole.actlist = []; this.myRole.netInfo.x = pos.x; this.myRole.netInfo.y = pos.y; this.roleNode.stopAllActions(); this.myRole.living_state = 0; GameModel.player.mapid = mapid; let gamelogic = (cc.find('Canvas')).getComponent('GameLogic'); gamelogic.uiLogic.setPosition(pos.x, pos.y); cc.sys.garbageCollect(); this.loadMap(true, pos); if (issend) { GameModel.send('c2s_change_map', { accountid: GameModel.player.accountid, roleId: GameModel.player.roleid, mapid: mapid, x: pos.x, y: pos.y }); } }, autoPatrol() { /* if (GameModel.player.teamid > 0) { return; } */ this.gamelogic.autoPatrolNode.active = true; let startX = Math.round((this.roleNode.getPosition().x - this.gridWidth / 2) / this.gridWidth); let startY = Math.round((this.roleNode.getPosition().y - this.gridHeight / 2) / this.gridHeight); let endX = Math.round((Math.floor(Math.random() * this.MAP_RES_WIDTH) - this.gridWidth / 2) / this.gridWidth); let endY = Math.round((Math.floor(Math.random() * this.MAP_RES_HEIGHT) - this.gridHeight / 2) / this.gridHeight); let result = this.searchMovePath(startX, startY, endX, endY); this.myRole.actlist = []; for (const act of result) { this.myRole.actlist.push({ type: 2, info: act }); } }, RoleStop() { if (GameModel.player.teamid > 0 && (!GameModel.player.tempLeave && !GameModel.player.isleader)) { return; } if (this.gamelogic.autoPatrolNode.active) { this.autoPatrol(); return; } for (const transfer of this.transferList) { if (SKUIUtil.distanceByVec2(this.roleNode.getPosition(), transfer.getPosition()) < 90) { let toinfo = GameModel.conf_transfer[transfer.__info_id__]; this.changeMap(toinfo.tomap, cc.v2(toinfo.tox, toinfo.toy)); } } }, loadMap(change, pos) { // this.gamelogic.autoPatrolNode.active = true; if (this.gamelogic.node.getChildByName('YinYaoXiangPanel')) { this.gamelogic.node.getChildByName('YinYaoXiangPanel').getComponent('YinYaoXiangPanel').closePanel(); } if (this.mapId != 0) { for (let yTileNum = 0; yTileNum < this.mapNodeArr.length; yTileNum++) { let list = this.mapNodeArr[yTileNum]; for (let xTileNum = 0; xTileNum < list.length; xTileNum++) { if (list[xTileNum] == 1) { this.mapNodeArr[yTileNum][xTileNum] = 0; } let amapnode = this.node.getChildByName(this.mapres + '_' + yTileNum + '_' + xTileNum); if (amapnode) { amapnode.destroy(); } } } } this.myRole.movePath = []; this.gamelogic.clearPlayerObjs(); CNpcMgr.ReloadNpcJson(); // cc.loader.releaseResDir(`Map/jpg/${this.mapres}`, cc.Texture2D); // cc.loader.releaseResDir(`Map/jpg/${this.mapres}`, cc.SpriteFrame); // this.node.destroyAllChildren(); // gamelogic.playerObjs = {}; this.mapId = GameModel.player.mapid; this.mapres = GameModel.conf_map[this.mapId].mapid; if (this.gamelogic.uiLogic) { this.gamelogic.uiLogic.setMapName(GameModel.conf_map[this.mapId].map_name); } this.MAP_RES_WIDTH = GameModel.conf_map[this.mapId].width; this.MAP_RES_HEIGHT = GameModel.conf_map[this.mapId].height; this.rowCount = Math.ceil(this.MAP_RES_HEIGHT / this.gridHeight); this.lineCount = Math.ceil(this.MAP_RES_WIDTH / this.gridWidth); this.myRole.gridHeight = this.gridHeight; this.myRole.gridWidth = this.gridWidth; this.myRole.canvasHeight = this.canvasHeight; this.myRole.canvasWidht = this.canvasWidht; this.myRole.onlyid = GameModel.player.onlyid; this.myRole.name = GameModel.player.name; this.mapNodeArr = []; //先聲明一維 let maprow = Math.ceil(this.MAP_RES_HEIGHT / this.mapNodeSize); let mapline = Math.ceil(this.MAP_RES_WIDTH / this.mapNodeSize); if (maprow < 1 || mapline < 1) { let info = `$警告:地圖[${this.mapId}:${this.mapres}]阻礙大小異常[${maprow}:${mapline}`; Report.report(info); } for (var i = 0; i < maprow; i++) { //一維長度為20 this.mapNodeArr[i] = new Array(mapline); //在聲明二維 for (var j = 0; j < mapline; j++) { //二維長度為20 this.mapNodeArr[i][j] = 0; } } this.width = cc.find('Canvas').width; this.height = cc.find('Canvas').height; this.mapScale = 0.8; this.node.scale = this.mapScale; this.npcInfo = GameModel.conf_map_list[this.mapres].npcInfo; this.gridInfoArr = GameModel.conf_map_list[this.mapres].mapInfo; this.myRole.gridInfoArr = this.gridInfoArr; this.myRole.actlist = []; this.gamelogic.autoNode.active = false; this.gamelogic.autoPatrolNode.active = false; this.gamelogic.mainMap.getComponent('MainMapLogic').removePathNodes(); this.startPos = GameModel.conf_map_list[this.mapres].startPos; this.assets = GameRes.mapResList[this.mapres]; // this.node.x = -this.width / 2; // this.node.y = -this.height / 2; if (change) { if (!pos) { this.myRole.setObjPos(this.startPos.x, this.startPos.y); // this.setTeamPos(this.startPos.x, this.startPos.y); } else { this.myRole.setObjPos(pos.x, pos.y); // this.setTeamPos(pos.x, pos.y); } } let rolePos = this.node.convertToWorldSpaceAR(this.roleNode.getPosition()); this.updateMap(cc.v2(this.width / 2 - rolePos.x, this.height / 2 - rolePos.y)); // this.scheduleOnce(() => { // // this.schedule(this.checkRolePos, 0.5, cc.macro.REPEAT_FOREVER); // this.complete = true; // }, 3); for (const transfer of this.transferList) { transfer.destroy(); } this.transferList = []; for (const key in GameModel.conf_transfer) { const info = GameModel.conf_transfer[key]; if (info.mapid == this.mapId) { let transfer = cc.instantiate(this.transferPre); transfer.x = info.mapx * 20; transfer.y = info.mapy * 20; // transfer.tag = info.id; transfer.__info_id__ = info.id; transfer.zIndex = 1; transfer.parent = this.node; this.transferList.push(transfer); } } if (this.mapId == 3001) { this.showGangBattleGate() GangWar.Instance.openBattleMainPanel() GameModel.player.getLogic().resetRoleTitle() GameModel.send("c2s_detail_statistics", {}) } else { if (this.gateRight) this.gateRight.destroy() if (this.gateLeft) this.gateLeft.destroy() GangWar.Instance.destroyPanel() } if (this.mapId == 4001) { let ui = cc.instantiate(this.homePre); ui.parent = this.node; ui.name = 'homeUI'; ui.zIndex = 1; } else if (this.node.getChildByName('homeUI') != null) { this.node.getChildByName('homeUI').destroy(); } let audio = GameUtil.getMapAudio(this.mapId); AudioUtil.playMusic(audio); }, showGangBattleGate() { if (this.gateRight) this.gateRight.destroy() if (this.gateLeft) this.gateLeft.destroy() let gateRight = cc.instantiate(this.effPre); gateRight.x = 3195; gateRight.y = 1746; gateRight.zIndex = 1; gateRight.name = "gateRight" gateRight.parent = this.node; this.gateRight = gateRight; cc.loader.loadRes(`shap/7205/stand_1`, cc.SpriteAtlas, function (error, atlas) { if (error) { cc.warn(`$警告:加載資源錯誤:${url}`); return; } if (!atlas) { return; } let curFrames = atlas.getSpriteFrames(); let curClip = cc.AnimationClip.createWithSpriteFrames(curFrames, 10); curClip.name = `eff`; curClip.wrapMode = cc.WrapMode.Loop; if (gateRight) gateRight.getComponent("Effect").CreateAndPlayAnimation(curClip, null) }) let gateLeft = cc.instantiate(this.effPre); gateLeft.x = 715; gateLeft.y = 495; gateLeft.zIndex = 1; gateLeft.name = "gateLeft" gateLeft.parent = this.node; this.gateLeft = gateLeft; cc.loader.loadRes(`shap/7205/stand_1`, cc.SpriteAtlas, function (error, atlas) { if (error) { cc.warn(`$警告:加載資源錯誤:${url}`); return; } if (!atlas) { return; } let curFrames = atlas.getSpriteFrames(); let curClip = cc.AnimationClip.createWithSpriteFrames(curFrames, 10); curClip.name = `eff`; curClip.wrapMode = cc.WrapMode.Loop; if (gateLeft) gateLeft.getComponent("Effect").CreateAndPlayAnimation(curClip, null) }) }, showGangBattleGateDie_right(gate = false) { if (this.gateRight) this.gateRight.destroy() let gateRight = cc.instantiate(this.effPre); gateRight.x = 3195; gateRight.y = 1746; gateRight.zIndex = 1; gateRight.name = "gateRight" gateRight.parent = this.node; this.gateRight = gateRight; if (gate) cc.loader.loadRes(`shap/7205/die_1`, cc.SpriteAtlas, function (error, atlas) { if (error) { cc.warn(`$警告:加載資源錯誤:${url}`); return; } if (!atlas) { return; } let curFrames = atlas.getSpriteFrames(); let curClip = cc.AnimationClip.createWithSpriteFrames(curFrames, 10); curClip.name = `eff`; curClip.wrapMode = cc.WrapMode.Loop; if (gateRight) gateRight.getComponent("Effect").CreateAndPlayAnimation(curClip, null) }) let gateEff = cc.instantiate(this.effPre); gateEff.x = 0 gateEff.y = 0 gateEff.parent = gateRight; cc.loader.loadRes(`shap/7205/die_1_ef`, cc.SpriteAtlas, function (error, atlas) { if (error) { cc.warn(`$警告:加載資源錯誤:${url}`); return; } if (!atlas) { return; } let curFrames = atlas.getSpriteFrames(); let curClip = cc.AnimationClip.createWithSpriteFrames(curFrames, 10); curClip.name = `eff`; curClip.wrapMode = cc.WrapMode.Loop; if (gateEff) gateEff.getComponent("Effect").CreateAndPlayAnimation(curClip, null) }) }, showGangBattleGateDie_left(gate = false) { if (this.gateLeft) this.gateLeft.destroy() let gateLeft = cc.instantiate(this.effPre); gateLeft.x = 715; gateLeft.y = 495; gateLeft.zIndex = 1; gateLeft.name = "gateLeft" gateLeft.parent = this.node; this.gateLeft = gateLeft; if (gate) cc.loader.loadRes(`shap/7205/die_1`, cc.SpriteAtlas, function (error, atlas) { if (error) { cc.warn(`$警告:加載資源錯誤:${url}`); return; } if (!atlas) { return; } let curFrames = atlas.getSpriteFrames(); let curClip = cc.AnimationClip.createWithSpriteFrames(curFrames, 10); curClip.name = `eff`; curClip.wrapMode = cc.WrapMode.Loop; if (gateLeft) gateLeft.getComponent("Effect").CreateAndPlayAnimation(curClip, null) }) let gateEff = cc.instantiate(this.effPre); gateEff.x = 0 gateEff.y = 0 gateEff.parent = gateLeft; cc.loader.loadRes(`shap/7205/die_1_ef`, cc.SpriteAtlas, function (error, atlas) { if (error) { cc.warn(`$警告:加載資源錯誤:${url}`); return; } if (!atlas) { return; } let curFrames = atlas.getSpriteFrames(); let curClip = cc.AnimationClip.createWithSpriteFrames(curFrames, 10); curClip.name = `eff`; curClip.wrapMode = cc.WrapMode.Loop; if (gateEff) gateEff.getComponent("Effect").CreateAndPlayAnimation(curClip, null) }) }, boomGangMap(info) { if (this.mapId != 3001) return if (info.type == 1) { // 龍神大砲 let longshenEff = cc.instantiate(this.effPre); longshenEff.x = info.x * 20; longshenEff.y = info.y * 20; longshenEff.zIndex = 1; longshenEff.name = "longshenEff"; longshenEff.parent = this.node; cc.loader.loadRes(`effect/2098`, cc.SpriteAtlas, function (error, atlas) { if (error) { cc.warn(`$警告:加載資源錯誤:${url}`); return; } if (!atlas) return; let curFrames = atlas.getSpriteFrames(); let curClip = cc.AnimationClip.createWithSpriteFrames(curFrames, 10); curClip.name = `eff`; curClip.wrapMode = cc.WrapMode.normal; longshenEff.getComponent("Effect").CreateAndPlayAnimation(curClip, null) }) } else if (info.type == 2) { // 烈火 let liehuoEff = cc.instantiate(this.effPre); liehuoEff.x = info.x * 20; liehuoEff.y = info.y * 20; liehuoEff.zIndex = 1; liehuoEff.name = "liehuoEff"; liehuoEff.parent = this.node; cc.loader.loadRes(`shap/7207/die_1_ef`, cc.SpriteAtlas, function (error, atlas) { if (error) { cc.warn(`$警告:加載資源錯誤:${url}`); return; } if (!atlas) return; let curFrames = atlas.getSpriteFrames(); let curClip = cc.AnimationClip.createWithSpriteFrames(curFrames, 10); curClip.name = `eff`; curClip.wrapMode = cc.WrapMode.normal; liehuoEff.getComponent("Effect").CreateAndPlayAnimation(curClip, null) }) } else if (info.type == 3) { // 玄冰 let xuanbingEff = cc.instantiate(this.effPre); xuanbingEff.x = info.x * 20; xuanbingEff.y = info.y * 20; xuanbingEff.zIndex = 1; xuanbingEff.name = "xuanbingEff"; xuanbingEff.parent = this.node; cc.loader.loadRes(`shap/7208/die_1_ef`, cc.SpriteAtlas, function (error, atlas) { if (error) { cc.warn(`$警告:加載資源錯誤:${url}`); return; } if (!atlas) return; let curFrames = atlas.getSpriteFrames(); let curClip = cc.AnimationClip.createWithSpriteFrames(curFrames, 10); curClip.name = `eff`; curClip.wrapMode = cc.WrapMode.normal; xuanbingEff.getComponent("Effect").CreateAndPlayAnimation(curClip, null) }) } }, updateMap(deltaPos) { this.node.x += deltaPos.x; this.node.y += deltaPos.y; //地圖層的位置在(-width/2, -height/2) let maxX = -this.width / 2; let maxY = -this.height / 2; if (this.node.x > maxX) { this.node.x = maxX; } if (this.node.y > maxY) { this.node.y = maxY; } let minh = -(this.MAP_RES_HEIGHT * this.mapScale - this.height) + maxY; let minw = -(this.MAP_RES_WIDTH * this.mapScale - this.width) + maxX; if (this.node.y < minh) { this.node.y = minh; } if (this.node.x < minw) { this.node.x = minw; } let tx = Math.abs(this.lastpos.x - this.node.x); let ty = Math.abs(this.lastpos.y - this.node.y); if (tx < 100 && ty < 100) { return; } this.lastpos = this.node.position; let currentNodeSize = this.mapNodeSize * this.mapScale; let startx = this.node.x + currentNodeSize * this.borderCount - maxX; if (startx >= 0) { startx = 0; } let endx = this.node.x - currentNodeSize * this.borderCount - maxX - this.width; if (endx < minw - this.width / 2) { endx = minw - this.width / 2; } let starty = this.node.y + currentNodeSize * this.borderCount - maxY; if (starty >= 0) { starty = 0; } let endy = this.node.y - maxY - this.height; if (endy < minh - this.height / 2) { endy = minh - this.height / 2; } let begin_w_n = Math.floor(Math.abs(startx) / currentNodeSize); let end_w_n = Math.ceil(Math.abs(endx) / currentNodeSize); let begin_h_n = Math.floor(Math.abs(starty) / currentNodeSize); let end_h_n = Math.ceil(Math.abs(endy) / currentNodeSize); for (let yTileNum = 0; yTileNum < this.mapNodeArr.length; yTileNum++) { let list = this.mapNodeArr[yTileNum]; for (let xTileNum = 0; xTileNum < list.length; xTileNum++) { const hadadd = list[xTileNum]; if (xTileNum >= begin_w_n && xTileNum <= end_w_n && yTileNum >= begin_h_n && yTileNum <= end_h_n) { if (hadadd == 0) { let mapNode = new cc.Node(); let mapframe = mapNode.addComponent(cc.Sprite); let self = this; let url = `Map/jpg/${this.mapres}/${this.mapres}_${yTileNum}_${xTileNum}`; cc.loader.loadRes(url, cc.SpriteFrame, function (error, frame) { if (error) { let info = `$警告:加載地圖資源${url}錯誤!`; Report.report(info); return; } if (SKUIUtil.isValid(mapframe.node)) { mapframe.spriteFrame = frame; } else { SKLogger.warn(`$警告:地圖塊資源節點無效${url}`); } mapNode.parent = self.node; mapNode.name = self.mapres + '_' + yTileNum + '_' + xTileNum; mapNode.setAnchorPoint(cc.v2(0, 0)); mapNode.setPosition(xTileNum * self.mapNodeSize, yTileNum * self.mapNodeSize); if (SKDataUtil.isArray(self.mapNodeArr) && self.mapNodeArr.length >= yTileNum) { let temp = self.mapNodeArr[yTileNum]; if (SKDataUtil.isArray(temp) && temp.length >= xTileNum) { self.mapNodeArr[yTileNum][xTileNum] = 1; } else { SKLogger.warn(`$警告:刷新地圖[${self.mapres}]JPG塊X坐標超出範圍${xTileNum}`); } } else { SKLogger.warn(`$警告:刷新地圖[${self.mapres}]JPG塊Y坐標超出範圍${yTileNum}`); } }); } } else { if (hadadd == 1) { this.node.getChildByName(this.mapres + '_' + yTileNum + '_' + xTileNum).destroy(); cc.loader.releaseRes(`Map/jpg/${this.mapres}/${this.mapres}_${yTileNum}_${xTileNum}`, cc.Texture2D); cc.loader.releaseRes(`Map/jpg/${this.mapres}/${this.mapres}_${yTileNum}_${xTileNum}`, cc.SpriteFrame); this.mapNodeArr[yTileNum][xTileNum] = 0; } } } } }, update() { if (this.loaded) { this.checkRolePos(); } }, checkRolePos() { let rolePos = this.node.convertToWorldSpaceAR(this.roleNode.getPosition()); let distance = SKUIUtil.distanceByVec2(cc.v2(this.width / 2, this.height / 2), rolePos); if (distance > 5) { let deltaPos = cc.v2(0, 0); if (rolePos.x - this.width / 2 > 0 || rolePos.x - this.width / 2 < 0) { // deltaPos.x = (this.width / 2 - rolePos.x) / 10; let direction = rolePos.x > this.width / 2 ? -1 : 1; deltaPos.x = direction * Math.sqrt(Math.abs(this.width / 2 - rolePos.x)) / 2; } if (rolePos.y - this.height / 2 > 0 || rolePos.y - this.height / 2 < 0) { // deltaPos.y = (this.height / 2 - rolePos.y) / 10; let direction = rolePos.y > this.height / 2 ? -1 : 1; deltaPos.y = direction * Math.sqrt(Math.abs(this.height / 2 - rolePos.y)) / 2; } this.updateMap(deltaPos); } }, touchPos(drawPos) { if (GameModel.player.teamid > 0 && !GameModel.player.isleader && !GameModel.player.tempLeave) { return []; } // 蓄力中則打斷 if (GameModel.needKeep) GameUtil.breakWaitTip2() this.cleanTeamPath(); let startX = Math.round((this.roleNode.getPosition().x - this.gridWidth / 2) / this.gridWidth); let startY = Math.round((this.roleNode.getPosition().y - this.gridHeight / 2) / this.gridHeight); let endX = Math.round((drawPos.x - this.gridWidth / 2) / this.gridWidth); let endY = Math.round((drawPos.y - this.gridHeight / 2) / this.gridHeight); let result = this.searchMovePath(startX, startY, endX, endY); this.myRole.actlist = []; this.roleNode.stopAllActions(); if (result.length > 0) { for (const act of result) { this.myRole.actlist.push({ type: 2, info: act }); } this.myRole.living_state = 0; } this.myRole.objUpdate(); this.gamelogic.autoNode.active = false; this.gamelogic.autoPatrolNode.active = false; this.gamelogic.mainMap.getComponent('MainMapLogic').removePathNodes(); this.showTouchEffect(drawPos); return result; }, cleanTeamPath() { if (GameModel.player.teamid == 0 || !GameModel.player.isleader || GameModel.player.tempLeave) { return; } if (!GameModel.player.teamInfo.objlist || !Array.isArray(GameModel.player.teamInfo.objlist)) { return; } for (let index = 1; index < GameModel.player.teamInfo.objlist.length; index++) { let obj = GameModel.player.teamInfo.objlist[index]; if (obj.livingtype != 1) { break; } let p = this.gamelogic.GetPlayerObjs(obj.onlyid); if (p) { let plogic = p.getComponent('role'); plogic.actlist = []; p.stopAllActions(); plogic.objUpdate(); } } }, setTeamPos(x, y) { if (GameModel.player.teamid == 0 || !GameModel.player.isleader) { return; } if (!GameModel.player.teamInfo.objlist || !Array.isArray(GameModel.player.teamInfo.objlist)) { return; } for (let index = 1; index < GameModel.player.teamInfo.objlist.length; index++) { let obj = GameModel.player.teamInfo.objlist[index]; if (obj.livingtype != 1 || obj.pause == 1) { break; } let p = this.gamelogic.GetPlayerObjs(obj.onlyid); if (p) { let plogic = p.getComponent('role'); plogic.setObjPos(x, y); } } }, setTeamPath() { if (GameModel.player.teamid == 0 || !GameModel.player.isleader) { return; } if (!GameModel.player.teamInfo.objlist || !Array.isArray(GameModel.player.teamInfo.objlist)) { return; } let path = this.myRole.movePath; if (path.length < 5) { return; } if (path.length > 30) { path.splice(0, path.length - 30); } // this.addTeamPlayerToMap(); for (let index = 1; index < GameModel.player.teamInfo.objlist.length; index++) { let obj = GameModel.player.teamInfo.objlist[index]; if (obj.livingtype != 1 || obj.pause == 1) { break; } let p = this.gamelogic.GetPlayerObjs(obj.onlyid); if (p) { let plogic = p.getComponent('role'); if (path.length > index * 5) { let pos = path[path.length - 5 * index - 1]; plogic.actlist.push({ type: 2, info: pos }); plogic.objUpdate(); } } } }, addTeamPlayerToMap() { if (GameModel.player.teamid == 0 || !GameModel.player.isleader) { return; } for (let index = 1; index < GameModel.player.teamInfo.objlist.length; index++) { let obj = GameModel.player.teamInfo.objlist[index]; if (obj.livingtype != 1 || obj.pause == 1) { break; } if (this.gamelogic.playerObjs[obj.onlyid] == null) { let curRole = cc.instantiate(this.rolepre); curRole.parent = this.node; curRole.zIndex = 3; curRole.livingtype = obj.livingtype; let comRole = curRole.getComponent('role'); comRole.setObjPos(this.myRole.netInfo.x, this.myRole.netInfo.y); comRole.setInfo(obj); comRole.onlyid = obj.onlyid; this.gamelogic.playerObjs[obj.onlyid] = curRole; } } }, showTouchEffect(pos) { let teffect = cc.instantiate(this.touchPre); teffect.parent = this.node; teffect.x = pos.x; teffect.y = pos.y; teffect.runAction(cc.sequence(cc.delayTime(3), cc.removeSelf())); }, searchMovePath(startX, startY, endX, endY) { let availableStart = this.getAvailabelPoint(startY, startX, this.gridInfoArr, this.rowCount, this.lineCount); let availableEnd = this.getAvailabelPoint(endY, endX, this.gridInfoArr, this.rowCount, this.lineCount); let result = this.searchRoad(availableStart.r, availableStart.l, availableEnd.r, availableEnd.l, this.gridInfoArr, this.rowCount, this.lineCount); return result; }, getAvailabelPoint(r, l, mapArr, rows, lines) { if (r < 0) { r = 0; } if (l < 0) { l = 0; } if (r >= rows) { r = rows - 1; } if (l >= lines) { l = lines - 1; } if (mapArr[r][l] != 0) { return { r: r, l: l }; } let count = 1; for (let i = 0; i < 10000000; i++) { if (count > lines && count > rows) { return { r: -1, l: -1 }; } if (r + count < rows && mapArr[r + count][l] != 0) { return { r: r + count, l: l }; } if (l + count < lines && mapArr[r][l + count] != 0) { return { r: r, l: l + count }; } if (r >= count && mapArr[r - count][l] != 0) { return { r: r - count, l: l }; } if (l >= count && mapArr[r][l - count] != 0) { return { r: r, l: l - count }; } if (r + count < rows && l + count < lines && mapArr[r + count][l + count] != 0) { return { r: r + count, l: l + count }; } if (r >= count && l >= count && mapArr[r - count][l - count] != 0) { return { r: r - count, l: l - count }; } if (r >= count && l + count < lines && mapArr[r - count][l + count] != 0) { return { r: r - count, l: l + count }; } if (l >= count && r + count < rows && mapArr[r + count][l - count] != 0) { return { r: r + count, l: l - count }; } count++; } }, /** * 小頂堆上升算法 * list 小頂堆列表 * pos 起始計算位置,即從改點開始上升 * indexlist 地圖節點索引,節點地圖坐標對應list中的位置 * cols 地圖列數 */ minheap_filterup(list, pos, indexlist, cols) { let c = pos; // 當前節點(current)的位置 let p = Math.floor((c - 1) / 2); // 父(parent)結點的位置 let tmp = list[c]; // 當前節點(current) while (c > 0) { // c>0 還未上升到頂部 if (list[p].F <= tmp.F) // 父節點比當前節點小,上升結束 break; else { list[c] = list[p]; // 父節點放到當前位置 indexlist[list[p].r * cols + list[p].l] = c; //設置父節點的索引位置 c = p; // 當前位置上升到父節點位置 p = Math.floor((p - 1) / 2); // 重新計算父節點位置 } } list[c] = tmp; // 把傳入節點放到上升位置 indexlist[tmp.r * cols + tmp.l] = c; // 設置傳入點的索引位置 }, /** * 小顶堆下沉算法 * list 小頂堆列表 * pos 起始計算位置,即從改點開始上升 * indexlist 地圖節點索引,節點地圖坐標對應list中的位置 * cols 地圖列數 */ minheap_filterdown(list, pos, indexlist, cols) { let c = pos; // 當前(current)節點的位置 let l = 2 * c + 1; // 左(left)孩子的位置 let tmp = list[c]; // 當前(current)節點 let end = list.length - 1; // 數組終點 while (l <= end) { if (l < end && list[l].F > list[l + 1].F) // "l"是左孩子,"l+1"是右孩子 l++; // 左右兩孩子中選擇較小者,即list[l+1] if (tmp.F <= list[l].F) // 當前節點比最小的子節點小,調整結束 break; else { list[c] = list[l]; indexlist[list[l].r * cols + list[l].l] = c; c = l; l = 2 * l + 1; } } list[c] = tmp; indexlist[tmp.r * cols + tmp.l] = c; }, existInCloseList(point, list, cols) { if (list[point.r * cols + point.l]) return true; return false; }, existInOpenList(point, list, cols) { if (list[point.r * cols + point.l]) return list[point.r * cols + point.l]; return false; }, //其中的MAP.arr是二維數組 searchRoad(start_r, start_l, end_r, end_l, mapArr, rows, cols) { if (end_r == -1 && end_l == -1) { return []; } var openList = [], //開啟列表 closeObjList = {}, //關閉列表索引 openObjList = {}, //開啟列表索引 result = [], //結果數組 result_index = 0; //終點位置 if (start_r == end_r && start_l == end_l) { return result; } openList.push({ r: start_r, l: start_l, G: 0 }); //把當前點加入到開啟列表中,並且G是0 openObjList[start_r * cols + start_l] = start_r * cols + start_l; do { var currentPoint = openList[0]; if (openList.length > 1) { openList[0] = openList[openList.length - 1]; this.minheap_filterdown(openList, 0, openObjList, cols); } openList.splice(openList.length - 1, 1); closeObjList[currentPoint.r * cols + currentPoint.l] = currentPoint; delete openObjList[currentPoint.r * cols + currentPoint.l]; var surroundPoint = this.SurroundPoint(currentPoint); for (var i in surroundPoint) { var item = surroundPoint[i]; //獲得周圍的八個點 if ( item.r >= 0 && //判斷是否在地圖上 item.l >= 0 && item.r < rows && item.l < cols && mapArr[item.r][item.l] != 0 && //判斷是否是障礙物 !this.existInCloseList(item, closeObjList, cols) && //判斷是否在關閉列表中 mapArr[item.r][currentPoint.l] != 0 && //判斷之間是否有障礙物,如果有障礙物是過不去的 mapArr[currentPoint.r][item.l] != 0) { //g 到父節點的位置 //如果是上下左右位置的則g等於10,斜對角的就是14 var g = currentPoint.G + ((currentPoint.r - item.r) * (currentPoint.l - item.l) == 0 ? 10 : 14); if (!this.existInOpenList(item, openObjList, cols)) { //如果不在開啟列表中 //計算H,通過水平和垂直距離進行確定 item['H'] = Math.abs(end_r - item.r) * 10 + Math.abs(end_l - item.l) * 10; item['G'] = g; item['F'] = item.H + item.G; item['parent'] = currentPoint; openList.push(item); openObjList[item.r * cols + item.l] = openList.length - 1; if (item['H'] == 0) { break; } this.minheap_filterup(openList, openList.length - 1, openObjList, cols); } else { //存在在開啟列表中,比較目前的g值和之前的g的大小 var index = this.existInOpenList(item, openObjList, cols); //如果當前點的g更小 if (g < openList[index].G) { openList[index].parent = currentPoint; openList[index].G = g; openList[index].F = g + openList[index].H; } this.minheap_filterup(openList, index, openObjList, cols); } } } //如果開啟列表空了,沒有通路,結果為空 if (openList.length == 0) { break; } // openList.sort(this.sortF);//這一步是為了循環回去的時候,找出 F 值最小的, 將它從 "開啟列表" 中移掉 } while (!(result_index = this.existInOpenList({ r: end_r, l: end_l }, openObjList, cols))); //判斷結果列表是否為空 if (!result_index) { result = []; } else { var currentObj = openList[result_index]; do { //把路勁節點添加到result當中 result.unshift({ r: currentObj.r, l: currentObj.l }); currentObj = currentObj.parent; } while (currentObj.r != start_r || currentObj.l != start_l); } let alpha = 0.8; let beta = 0.2; let p = result.slice(0); for (let i = 1; i <= 8; i++) { for (let k = 2; k < p.length - 1; k++) { let t = p[k]; let l = p[k - 1]; let n = p[k + 1]; t.l = t.l + alpha * (result[k].l - t.l) + beta * (l.l - 2 * t.l + n.l); t.r = t.r + alpha * (result[k].r - t.r) + beta * (l.r - 2 * t.r + n.r); } } return p; // return result; }, //用F值對數組排序 sortF(a, b) { return b.F - a.F; }, //獲取周圍八個點的值 SurroundPoint(curPoint) { var r = curPoint.r, l = curPoint.l; return [{ r: r - 1, l: l - 1 }, { r: r, l: l - 1 }, { r: r + 1, l: l - 1 }, { r: r + 1, l: l }, { r: r + 1, l: l + 1 }, { r: r, l: l + 1 }, { r: r - 1, l: l + 1 }, { r: r - 1, l: l } ]; }, //判斷點是否存在在列表中,是的話返回的是序列號 existList(point, list) { for (var i in list) { if (point.r == list[i].r && point.l == list[i].l) { return i; } } return false; }, });