import { SoundManager } from "../../../component/SoundManager"; import { SoundName } from "../../../Global"; import { Battle } from "../Battle"; import { ObjType } from "../BattleConst"; import { BigBombBlockData } from "./BigBombBlockData"; import { BlockData } from "./BlockData"; import { BlockSkillBomb } from "./blockSkill/BlockSkillBomb"; import { BlockSkillDiamond } from "./blockSkill/BlockSkillDiamond"; import { BlockSkillFirework } from "./blockSkill/BlockSkillFirework"; import { BlockSkillNail } from "./blockSkill/BlockSkillNail"; import { BlockSkillSwitcher } from "./blockSkill/BlockSkillSwitcher"; import { LaserObj } from "./LaserObj"; import { ObjData } from "./ObjData"; import { ObjDataUtil } from "./ObjDataUtil"; import { PatrolObj } from "./PatrolObj"; import { PlusOneObj } from "./PlusOneObj"; import { PotObj } from "./PotObj"; import { RectBlockData } from "./RectBlockData"; import { RotaterObj } from "./RotaterObj"; import { SolidColorBlockData } from "./SolidColorBlockData"; import { SpliterObj } from "./SpliterObj"; import { StaticNailBlockData } from "./StaticNailBlockData"; import { TrangleBlockData } from "./TrangleBlockData"; /**格子0,0点在左上角,向右下方增长,格子坐标都为正数 */ export class MapData { private static UID: number = 0; private _gridSize: cc.Vec2 = cc.v2(0, 0); /**单个格子的像素尺寸 */ public get gridSize(): cc.Vec2 { return this._gridSize; } private _mapGridSize: cc.Vec2 = cc.v2(0, 0); /**地图的格子尺寸 */ get mapGridSize(): cc.Vec2 { return this._mapGridSize; } private _blockData: Map = new Map(); /** objData的子集,只包含砖块,由blockdata自己维护 */ get blockData(): Map { return this._blockData; } private _rectBlockList: RectBlockData[] = []; private _objData: Map = new Map(); /**所有物体, 由objdata自己维护 */ get objData(): Map { return this._objData; } private _id: number = 0; /**唯一uid */ get id(): number { return this._id; } private _levelId: number = 0; get levelId(): number { return this._levelId; } private _totalScore: number = 0; /**所有砖块的总分 */ get totalScore(): number { return this._totalScore; } private _curScore: number = 0; /**当前的得分 */ get curScore(): number { return this._curScore; } private _roundBlockCombo: number = 0; /**显示和隐藏的分界线, y值小于等于此值的,不显示 */ private _viewSplitRow: number; get viewSplitRow(): number { return this._viewSplitRow; } private _maxContentY: number = 0; /**有物件(圆点技能、砖块)的最大Y坐标 */ get maxContentY(): number { return this._maxContentY; } /**战斗引用 */ battle: Battle = null; clone(): MapData { let ret = new MapData(); MapData.UID++; ret._id = MapData.UID; ret._levelId = this._levelId; ret._gridSize.set(this._gridSize); ret._mapGridSize.set(this._mapGridSize); ret._totalScore = this._totalScore; ret._curScore = this._curScore; ret._viewSplitRow = this._viewSplitRow; ret._maxContentY = this._maxContentY; this._objData.forEach((value, key, map) => { let newData = value.clone(); newData.map = ret; ret._objData.set(key, newData); if (newData instanceof BlockData) { ret._blockData.set(key, newData); if (newData instanceof RectBlockData) { ret._rectBlockList.push(newData); } } }, this); return ret; } init(tiledMap: cc.TiledMap) { MapData.UID++; this._id = MapData.UID; this._levelId = Number(tiledMap.tmxAsset.name.split('-')[1]); let gridSize = tiledMap.getTileSize(); this._gridSize.x = gridSize.width; this._gridSize.y = gridSize.height; let mapSize = tiledMap.getMapSize(); this._mapGridSize.x = mapSize.width; this._mapGridSize.y = mapSize.height; this._viewSplitRow = mapSize.height - Math.floor(mapSize.width * 1.27) - 1; let skillLayer = tiledMap.getLayer('0'); for (let x: number = 0; x < mapSize.width; ++x) { for (let y: number = 0; y < mapSize.height; ++y) { let layers = tiledMap.getLayers(); for (let i = 0; i < layers.length; ++i) { let layer = layers[i]; let gid = layer.getTileGIDAt(x, y); let isSkillLayer: boolean = (layer == skillLayer); //#region 规则 //圆点技能(不带数字,不需要和砖块组合)可以放所有层 //需要和砖块组合的技能(有数字的),只能放在0层 //#endregion if (gid > 0) { let hp = (isSkillLayer ? 0 : Number(layer.getLayerName())); let skillGid = isSkillLayer ? gid : (skillLayer ? skillLayer.getTileGIDAt(x, y) : 0); //技能层直接使用gid,否则 读取技能层的gid, 没有技能层则为0 //不带砖块的技能 if (gid == ObjType.PLUS_ONE) { //+1球 let foo = new PlusOneObj(); foo.init(this, ObjType.PLUS_ONE, x, y); } else if (gid == ObjType.SPLITER) { let foo = new SpliterObj(); foo.init(this, ObjType.SPLITER, x, y); } else if (gid >= ObjType.LANCER_1 && gid <= ObjType.LANCER_3) { let foo = new LaserObj(); foo.init(this, gid, x, y); } else if (gid == ObjType.BIG_BOMB || gid == ObjType.BIG_BOMB_33) { let foo = new BigBombBlockData(); if (gid == ObjType.BIG_BOMB) { foo.initBlock(this, gid, hp, x, y - 1, 2, 2); this._rectBlockList.push(foo); } else if (gid == ObjType.BIG_BOMB_33) { foo.initBlock(this, gid, hp, x, y - 2, 3, 3); this._rectBlockList.push(foo); } } else if (gid == ObjType.POT) { let foo = new PotObj(); foo.init(this, gid, x, y); } else if (gid == ObjType.ROTATER) { let foo = new RotaterObj(); foo.init(this, gid, x, y); } else if (gid == ObjType.STATIC_IRON) { let foo = new StaticNailBlockData(); foo.init(this, gid, x, y); } else if (gid == ObjType.PATROL) { let foo = new PatrolObj(); foo.init(this, gid, x, y); } else if (!isSkillLayer) { //不在技能层,才创建砖块 let blockData: BlockData; let type: ObjType = ObjType.NORMAL; if (gid >= ObjType.TRANGLE_1 && gid <= ObjType.TRANGLE_4) { blockData = new TrangleBlockData(); type = gid; } else { if (gid >= ObjType.SOLID_1 && gid <= ObjType.SOLID_13) { blockData = new SolidColorBlockData(); type = gid; } else { //普通砖块 blockData = new BlockData(); } if (skillGid == ObjType.DIAMOND) { // type = ObjType.DIAMOND; blockData.addSkill(new BlockSkillDiamond(blockData)); } else if (skillGid == ObjType.BOMB) { // type = ObjType.BOMB; blockData.addSkill(new BlockSkillBomb(blockData)); } else if (skillGid == ObjType.STATIC) { blockData.addSkill(new BlockSkillNail(blockData)); } else if (skillGid >= ObjType.FIREWORK_VERTICAL && skillGid <= ObjType.FIREWORK_DOUBLE) { blockData.addSkill(new BlockSkillFirework(blockData, skillGid - 42)); } else if (skillGid == ObjType.SWITCHER) { blockData.addSkill(new BlockSkillSwitcher(blockData, false)); } } blockData.initBlock(this, type, hp, x, y); } if (y > this._maxContentY) { this._maxContentY = y; } } } } } let patrolList: { patrolIndex: number, patrolType: number, mapIndex: number }[] = []; let objLayer = tiledMap.getObjectGroup('obj'); if (objLayer) { let objs = objLayer.getObjects(); for (let i = 0; i < objs.length; ++i) { let type: string = objs[i]['type']; if (type == 'rect') { let pos = objs[i]['offset'] as cc.Vec2; let indexX = Math.floor(pos.x / this.gridSize.x); let indexY = Math.floor(pos.y / this.gridSize.y); let endIndexX = Math.floor((pos.x + objs[i]['width']) / this.gridSize.x); let endIndexY = Math.floor((pos.y + objs[i]['height']) / this.gridSize.y); let index = ObjDataUtil.getIndex(indexX, indexY); let block = this._blockData.get(index); if (block) { let width: number = endIndexX - indexX + 1; let height: number = endIndexY - indexY + 1; //已经创建的单个格子 let foo: RectBlockData; if (block instanceof SolidColorBlockData) { foo = new SolidColorBlockData(); foo.initBlock(this, block.type, block.hp, block.gridPos.x, block.gridPos.y, width, height); } else { foo = new RectBlockData(); foo.initBlock(this, ObjType.NORMAL, block.hp, block.gridPos.x, block.gridPos.y, width, height); } // block.addSkill() if (block.skill) { foo.addSkill(block.skill); block.skill = null; } this._rectBlockList.push(foo); if (foo.contentY > this._maxContentY) { this._maxContentY = foo.contentY; } } } else if (type && type.includes('trans')) { let pos = objs[i]['offset'] as cc.Vec2; let patrolType = -1; if (type.includes('transIn')) { patrolType = 0;//入口 } else if (type.includes('transOut')) { patrolType = 1; //出口 } if (patrolType > -1) { //配置有效 let patrolIndex = Number(type.split('-')[1]); let indexX = Math.floor(pos.x / this.gridSize.x); let indexY = Math.floor(pos.y / this.gridSize.y); let objIndex = ObjDataUtil.getIndex(indexX, indexY); let obj = this.objData.get(objIndex); if (obj && obj instanceof PatrolObj) { let foo = { patrolType: patrolType, patrolIndex: patrolIndex, mapIndex: objIndex }; patrolList.push(foo); } } } else if (type && type == 'switcherOpen') { let pos = objs[i]['offset'] as cc.Vec2; // let patrolType = -1; // if (type.includes('transIn')) { // patrolType = 0;//入口 // } // else if (type.includes('transOut')) { // patrolType = 1; //出口 // } // if (patrolType > -1) { // 配置有效 // let patrolIndex = Number(type.split('-')[1]); let indexX = Math.floor(pos.x / this.gridSize.x); let indexY = Math.floor(pos.y / this.gridSize.y); let objIndex = ObjDataUtil.getIndex(indexX, indexY); let obj = this.objData.get(objIndex); if (obj && obj instanceof BlockData && obj.skill instanceof BlockSkillSwitcher) { obj.skill.setDefaultState(true); } // } } } } patrolList.sort((a, b) => { if (a.patrolIndex - b.patrolIndex == 0) { return a.patrolType - b.patrolType; } else { return a.patrolIndex - b.patrolIndex; } }); //按 index 从小到大 入口、出口的顺序排列 for (let i = 0; i < patrolList.length; ++i) { let obj = this.objData.get(patrolList[i].mapIndex) as PatrolObj obj.initPatrolData(patrolList[i].patrolIndex, patrolList[i].patrolType, i % 2 == 0 ? patrolList[i + 1].mapIndex : patrolList[i - 1].mapIndex); } let blockNum = this._blockData.size; for (let i = 0; i < blockNum; ++i) { this._totalScore += (i * 10); } // console.log(); } private _retCache: cc.Vec2 = new cc.Vec2(0, 0); /** * * @param gridPos * @returns 返回实例是唯一的实例,不可缓存,可缓存返回实例的副本 */ getPixelPosByGridPos(gridPos: cc.Vec2): cc.Vec2 { let totalWidth = this._mapGridSize.x * this._gridSize.x; let totalHeight = this._mapGridSize.y * this._gridSize.y; this._retCache.x = gridPos.x * this._gridSize.x + this._gridSize.x / 2; this._retCache.y = gridPos.y * this._gridSize.y + this._gridSize.y / 2; this._retCache.x -= totalWidth / 2; this._retCache.y = -this._retCache.y + totalHeight / 2; return this._retCache; } onObjDead(obj: ObjData) { // if(this._rectBlockList.includes(obj)) if (obj instanceof BlockData) { let index = obj.index if (this._blockData.has(index)) { this._blockData.delete(index); if (obj instanceof RectBlockData) { this._roundBlockCombo += (obj.widthGrid * obj.heightGrid); //大格子按面积数计算连击 let index = this._rectBlockList.indexOf(obj); if (index > -1) { this._rectBlockList.splice(index, 1) } } else { this._roundBlockCombo++; } this._curScore += (this._roundBlockCombo * 10); this.battle && this.battle.onBlockDead(this._roundBlockCombo); } } if (this._objData.has(obj.index)) { this._objData.delete(obj.index); this.battle && this.battle.onObjDead(); } } /** * * @returns 是否有格子到达最下层 */ slideDown(): boolean { let list: ObjData[] = []; let ret = false; /**倒数第二行警告 */ let warn: boolean = false; this._objData.forEach((value, key, map) => { list.push(value); }, this); list.sort((a, b) => { // let aValue = a.gridPos.y; // if(a instanceof RectBlockData) { // aValue = // } // let bValue = b.gridPos.y; return b.gridPos.y - a.gridPos.y; }); //靠下的格子排数组前面 for (let i = 0; i < list.length; ++i) { let value = list[i]; if (!value.canSlide) { continue; } let canSlide = true; // let nextY:number = value. if (value instanceof RectBlockData) { if (value.canSlide) { //检查每一列的下一格 for (let x = 0; x < value.widthGrid; ++x) { // let nextBlock = this.getBlockByGridPos(value.gridPos.x + x, value.contentY + 1); // if (nextBlock) { // canSlide = false; // break; // } // else { // let nextIndex = ObjDataUtil.getIndex(value.gridPos.x + x, value.contentY + 1); // if (this._objData.has(nextIndex)) { // canSlide = false; // break; // } // } if (!this.isGridEmpty(value.gridPos.x + x, value.contentY + 1)) { canSlide = false; break; } } } else { canSlide = false; } } else { // if (this.getBlockByGridPos(value.gridPos.x, value.gridPos.y + 1)) { // canSlide = false; //下一行有格子 // } // else { // let nextIndex = value.index + 1;//下一行的Index // if (this._objData.has(nextIndex)) { // canSlide = false; //下一行有任意物件 // } // } if (!this.isGridEmpty(value.gridPos.x, value.gridPos.y + 1)) { canSlide = false; } } if (canSlide && value.slideDown()) { if (!warn) { if (value instanceof BlockData && value.contentY == this.mapGridSize.y - 2) { warn = true; } } if (value.isReachedDownBorder()) { if (value instanceof BlockData) { ret = true; } else { //非block及其子类的销毁 value.dead(); } } } } if (warn && !ret) { SoundManager.ins.playEffect(SoundName.WARNING); } return ret; } isGridEmpty(gridX: number, gridY: number): boolean { let index = ObjDataUtil.getIndex(gridX, gridY); if (this._objData.has(index)) { return false; } else { if (this.getBlockByGridPos(gridX, gridY)) { return false; } } return true; // if (this.getBlockByGridPos(gridX, gridY)) { // canSlide = false; //下一行有格子 // } // else { // let nextIndex = value.index + 1;//下一行的Index // if (this._objData.has(nextIndex)) { // canSlide = false; //下一行有任意物件 // } // } } roundFinish() { this._roundBlockCombo = 0; } getBlockByGridPos(gridX: number, gridY: number): BlockData { let index = ObjDataUtil.getIndex(gridX, gridY); if (this._blockData.has(index)) { //快速判断 return this._blockData.get(index); } else { //检索大格子 for (let i = 0; i < this._rectBlockList.length; ++i) { // if(gridX == d) let rect = this._rectBlockList[i]; if (gridX >= rect.gridPos.x && gridX <= rect.gridPos.x + rect.widthGrid - 1 && gridY >= rect.gridPos.y && gridY <= rect.gridPos.y + rect.heightGrid - 1) { return rect; } } return null; } } battleStart() { this._objData.forEach((value, key, map) => { value.onBattleStart(); }, this) } }