//查找一定范围内的敌人 public List <BattleUnit> SearchBattleUnits(GridUnit centerGridUnit, int range) { List <BattleUnit> battleUnits = new List <BattleUnit>(); BattleMap battleMap = centerGridUnit.battleMap; bool[,] flag = new bool[battleMap.mapWidth, battleMap.mapHeight]; flag[centerGridUnit.column, centerGridUnit.row] = true; Queue <GridUnit> checkList = new Queue <GridUnit>(); GridUnit currentUnit = centerGridUnit; checkList.Enqueue(currentUnit); while (checkList.Count > 0) { currentUnit = checkList.Dequeue(); List <GridUnit> gridUnitList = battleMap.GetNearbyGrid(currentUnit); foreach (GridUnit gridUnit in gridUnitList) { if (range < centerGridUnit.Distance(gridUnit)) { continue; } if (!flag[gridUnit.column, gridUnit.row]) { flag[gridUnit.column, gridUnit.row] = true; if (gridUnit.battleUnit != null) { battleUnits.Add(gridUnit.battleUnit); } checkList.Enqueue(gridUnit); } } } return(battleUnits); }
public GridUnit(BattleMap battleMap, int row, int column) { //gridType = GridType.None; m_GridAttribute = new GridAttribute(); this.battleMap = battleMap; this.row = row; this.column = column; }
//查找所有可以到达的格子 public List <GridUnit> GetAccessibleGrids(BattleUnit battleUnit, BattleMap battleMap) { List <GridUnit> AccessibleGrids = new List <GridUnit>(); bool[,] flag = new bool[battleMap.mapWidth, battleMap.mapHeight]; flag[battleUnit.mapGrid.column, battleUnit.mapGrid.row] = true; Queue <PathTraceData> checkList = new Queue <PathTraceData>(); PathTraceData currentUnit = new PathTraceData(battleUnit.battleUnitAttribute.mobility, battleUnit.mapGrid); checkList.Enqueue(currentUnit); while (checkList.Count > 0) { currentUnit = checkList.Dequeue(); List <GridUnit> gridUnitList = battleMap.GetNearbyGrid(currentUnit.currentGridUnit); foreach (GridUnit gridUnit in gridUnitList) { float MovePointRemainder = currentUnit.MovePointRemainder - currentUnit.currentGridUnit.m_GridAttribute.m_CrossCost; //绝对障碍不可通过 if (gridUnit.GridType == GridType.Obstacle) { continue; } //不能跳过去,高度太高 if (gridUnit.m_GridAttribute.m_Height - currentUnit.currentGridUnit.m_GridAttribute.m_Height > battleUnit.battleUnitAttribute.springPower) { continue; } //体积太大穿不过去 if (gridUnit.m_GridAttribute.m_MaxPassVolume < battleUnit.battleUnitAttribute.volume) { continue; } //剩余移动点数不足 if (MovePointRemainder < 0) { continue; } //有敌人挡着(暂时还没判是否是友方) if (gridUnit.battleUnit != null && gridUnit.battleUnit.CanAction && !gridUnit.NavigationPassable) { continue; } if (!flag[gridUnit.column, gridUnit.row]) { flag[gridUnit.column, gridUnit.row] = true; AccessibleGrids.Add(gridUnit); checkList.Enqueue(new PathTraceData(MovePointRemainder, gridUnit)); } } } return(AccessibleGrids); }
public void Init( int mapWidth, int mapHeight, int obstacleCount, int obstacleGap, int buffCount, int itemCount, List <SO_BattleUnitAttribute> teamA, List <SO_BattleUnitAttribute> teamB) { //生成地图 battleMap = BattleMapCreator.Instance.Create(mapWidth, mapHeight, obstacleCount, obstacleGap, buffCount, itemCount); battleMap.battleField = this; //生成战斗小组 GenerateBattleTeam(teamA, teamB); }
public static GridUnit[] ReadScene1LocationFromXml(BattleMap map, string xmlFilePath, int teamKind, int gridCount) { GridUnit[] bornGrids = new GridUnit[gridCount]; int x = 0, y = 0; //GridUnit tmpGrid = new GridUnit(map, 0, 0); XmlDocument xmlDoc = null; //TextAsset xmlfile = Resources.Load(xmlFilePath) as TextAsset; //UtilityHelper.LogFormat("begin reading skill xml file from {0}", xmlFilePath); Object asset = Resources.Load(xmlFilePath); ResourceUnit xmlfileUnit = new ResourceUnit(null, 0, asset, null, ResourceType.ASSET); TextAsset xmlfile = xmlfileUnit.Asset as TextAsset; if (!xmlfile) { return(bornGrids); } UtilityHelper.Log("read scene 1 location xml successful"); xmlDoc = new XmlDocument(); xmlDoc.LoadXml(xmlfile.text); XmlNodeList infoNodeList = xmlDoc.SelectSingleNode("Locations").ChildNodes; for (int i = 0; i < infoNodeList.Count; i++) {//(XmlNode xNode in infoNodeList) if ((infoNodeList[i] as XmlElement).GetAttributeNode("un32ID") == null) { continue; } string typeName = (infoNodeList[i] as XmlElement).GetAttributeNode("un32ID").InnerText; int id = (int)Convert.ToUInt32(typeName); if (id != teamKind) { continue; } foreach (XmlElement xEle in infoNodeList[i].ChildNodes) { switch (xEle.Name) { case "row": { x = Convert.ToInt32(xEle.InnerText); } break; case "column": { y = Convert.ToInt32(xEle.InnerText); } break; } } //tmpGrid.localPosition = new Vector3((tmpGrid.column + 1)* EGameConstL.Map_GridWidth, -(tmpGrid.row + 1)* EGameConstL.Map_GridOffsetY, 0); //Debug.LogFormat("i = {0}, row = {1}, column = {2}, position = {3}", i, tmpGrid.row, tmpGrid.column, tmpGrid.localPosition); //Debug.LogFormat("i = {0}, row = {1}, column = {2}, position = {3}", i, x, y, map.mapGrids[y, x].localPosition); if (teamKind == 0) { bornGrids[i] = map.mapGrids[y, x]; } else if (teamKind == 1) { bornGrids[i - 1] = map.mapGrids[y, x]; } } return(bornGrids); }
/// <summary> /// 导航至某个位置 /// </summary> /// <returns>The navigate.</returns> /// <param name="battleMap">地图</param> /// <param name="from">起始格子</param> /// <param name="to">目标格子</param> /// <param name="path">保存导航路径</param> /// <param name="searched">搜索过的路径</param> /// <param name="mobility">步数限制(移动区域半径)</param> /// <param name="stopDistance">距离目标的停止距离</param> /// <param name="containsTargetGrid">路径是否包含目标</param> public bool Navigate( BattleMap battleMap, GridUnit from, GridUnit to, List <GridUnit> path, List <GridUnit> searched = null, int mobility = -1, int stopDistance = 0) { //没有设置地图 if (battleMap == null) { return(false); } if (path != null) { path.Clear(); } if (searched != null) { searched.Clear(); } //这种情况基本上也就不用寻路了吧... if (to.runtimePasses == 0 && stopDistance <= 1 && from.Distance(to) > 1) { return(false); } //本来就在停止距离内 if (from.Distance(to) <= stopDistance) { return(true); } int tryTimes = battleMap.GridCount; List <NavigationData> opening = new List <NavigationData>(); opening.Add(GetEmptyNavigationData(from, null, 0, from.Distance(to))); int retry = 0; bool catched = false; //当前探索方向 int curDir = 0; //上次探索方向 int lastDir = 0; //每次检测方向的次数 int checkTimes = 0; //判断是否需要遍历open列表 NavigationData gift = null; //距离最近的格子(接下来要移动的) NavigationData next_0 = null; //距离次近的格子 NavigationData next_1 = null; int minStep = EGameConstL.Infinity; while (retry <= tryTimes && !catched) { ++retry; //从open中查找最近的节点 if (gift != null) { next_0 = gift; gift = null; } else if (next_1 != null) { next_0 = next_1; next_1 = null; } else { minStep = EGameConstL.Infinity; if (opening.Count == 0) { break; } for (int i = opening.Count - 1; i >= 0; --i) { if (!opening[i].open) { opening.RemoveAt(i); } else if (opening[i].F < minStep) { next_0 = opening[i]; minStep = next_0.F; } else if (next_1 == null && next_0 != null && opening[i].F == next_0.F) { next_1 = opening[i]; } } } //标志为已关闭 next_0.open = false; //放入已搜索中 if (searched != null) { searched.Add(next_0.thisGrid); } checkTimes = 6; curDir = lastDir; //遍历最近节点的周围6个节点,依次放入close中 int roads = next_0.thisGrid.NavigationPassable ? 63 : next_0.thisGrid.roadPasses; while (checkTimes > 0) { //沿着当前探索方向继续探索 if ((roads & (1 << curDir)) != 0) { //获取该路通向的下一个item GridUnit sibling = battleMap.GetGridByDir(next_0.thisGrid.row, next_0.thisGrid.column, curDir); if (sibling == null) { //没路 ++curDir; curDir = (curDir > 5) ? 0 : curDir; --checkTimes; continue; } //如果这个不能移动 else if (sibling.GridType == GridType.Obstacle && !sibling.NavigationPassable) { //没路 ++curDir; curDir = (curDir > 5) ? 0 : curDir; --checkTimes; continue; } //如果这个格子有战斗单位且可以战斗 else if (sibling.battleUnit != null && sibling.battleUnit.CanAction && !sibling.NavigationPassable) { //无法通过 ++curDir; curDir = (curDir > 5) ? 0 : curDir; --checkTimes; continue; } //如果这个item就是目标或者已经进入了停止距离 else if ((stopDistance > 0 && sibling.Distance(to) <= stopDistance) || sibling.Equals(to)) { catched = true; if (path != null) { path.Add(sibling); NavigationData current = next_0; while (current != null) { if (current.thisGrid != from) { path.Add(current.thisGrid); } current = current.preGrid; } //翻转一下 path.Reverse(); } break; } else { //尝试判断这个是否为closed NavigationData nd = sibling.tempRef == null ? null : (NavigationData)(sibling.tempRef); if (nd == null) { //这个格子没有探索过,新建并添加 nd = GetEmptyNavigationData(sibling, next_0, next_0.G + 1, sibling.Distance(to)); //这个格子不错哦 if (nd.F <= next_0.F && gift == null) { //保存礼物 gift = nd; //记录下次起始的更新方向 lastDir = curDir; } //比第二目标好 else if (next_1 != null && nd.F < next_1.F) { //替换第二目标 next_1 = nd; opening.Add(nd); } else { //已经设置了礼物,因此只能放入opening列表中,以后再更新了呢 opening.Add(nd); } } else { //只处理没有被探索过的格子 if (nd.open) { //已经在Open列表中了 if ((next_0.G + 1) < nd.G) { //比原来的近,应该不可能 nd.G = next_0.G + 1; nd.H = sibling.Distance(to); nd.F = nd.G + nd.H; nd.preGrid = next_0; nd.thisGrid = sibling; } //这个格子不错哦 if (nd.F <= next_0.F && gift == null) { gift = nd; //保存当前探索方向 lastDir = curDir; } else if (next_1 != null && nd.F < next_1.F) { //替换第二目标 next_1 = nd; } } } } } ++curDir; curDir = (curDir > 5) ? 0 : curDir; --checkTimes; } } opening.Clear(); //重置池子 ResetPool(); //有步数限制 if (catched && path != null && mobility > 0) { for (int i = 0; i < path.Count; ++i) { if (path[i].Distance(from) > mobility) { path.RemoveRange(i, path.Count - i); break; } } } return(catched); }
//寻找某点到另一点的路径 public bool NewNavigate( BattleUnit battleUnit, BattleMap battleMap, GridUnit from, GridUnit to, List <GridUnit> path, int stopDistance = 0) { PathTraceData[,] flag = new PathTraceData[battleMap.mapWidth, battleMap.mapHeight]; PriorityQueue <PathTraceData> checkList = new PriorityQueue <PathTraceData>(); PathTraceData currentUnit = new PathTraceData(battleUnit.battleUnitAttribute.mobility, from); flag[from.column, from.row] = currentUnit; bool isFind = false; checkList.Push(currentUnit); while (checkList.Count > 0) { currentUnit = checkList.Pop(); if (currentUnit.currentGridUnit.Distance(to) <= stopDistance) { isFind = true; break; } List <GridUnit> gridUnitList = battleMap.GetNearbyGrid(currentUnit.currentGridUnit); foreach (GridUnit gridUnit in gridUnitList) { float MovePointRemainder = currentUnit.MovePointRemainder - currentUnit.currentGridUnit.m_GridAttribute.m_CrossCost; //绝对障碍不可通过 if (gridUnit.GridType == GridType.Obstacle) { continue; } //不能跳过去,高度太高 if (gridUnit.m_GridAttribute.m_Height - currentUnit.currentGridUnit.m_GridAttribute.m_Height > battleUnit.battleUnitAttribute.springPower) { continue; } //体积太大穿不过去 if (gridUnit.m_GridAttribute.m_MaxPassVolume < battleUnit.battleUnitAttribute.volume) { continue; } //剩余移动点数不足 //if (MovePointRemainder <= 0) continue; //有敌人挡着(暂时还没判是否是友方) if (gridUnit.battleUnit != null && gridUnit.battleUnit.CanAction && !gridUnit.NavigationPassable) { continue; } if (flag[gridUnit.column, gridUnit.row] == null || flag[gridUnit.column, gridUnit.row].MovePointRemainder < MovePointRemainder) { flag[gridUnit.column, gridUnit.row] = currentUnit; checkList.Push(new PathTraceData(MovePointRemainder, gridUnit)); } } } if (!isFind) { return(false); } path.Clear(); Stack <GridUnit> temp = new Stack <GridUnit>(); while (!currentUnit.currentGridUnit.Equals(from)) { if (currentUnit.MovePointRemainder >= 0) { temp.Push(currentUnit.currentGridUnit); } currentUnit = flag[currentUnit.currentGridUnit.column, currentUnit.currentGridUnit.row]; } while (temp.Count != 0) { path.Add(temp.Pop()); } return(true); }
public static BattleMap ReadBattleMapFromXML(string xmlFilePath) { TextAsset xmlfile = Resources.Load(xmlFilePath) as TextAsset; if (!xmlfile) { UtilityHelper.LogFormat("Load {0} xml file failed!", xmlFilePath); return(null); } int mapWidth = 0; int mapHeight = 0; GridUnit[,] gridMap = null; XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(xmlfile.text); XmlNodeList xmlNodeList = xmlDoc.SelectSingleNode("MapBaseMsg").ChildNodes; XmlNodeList mapMsgList = null; foreach (XmlElement xmlElement in xmlNodeList) { switch (xmlElement.Name) { case ("Width"): mapWidth = Convert.ToInt32(xmlElement.InnerText); break; case ("Height"): mapHeight = Convert.ToInt32(xmlElement.InnerText); break; case ("GridMsg"): mapMsgList = xmlElement.ChildNodes; break; } } BattleMap battleMap = new BattleMap(mapWidth, mapHeight); foreach (XmlElement gridUnitInfo in mapMsgList) { int posX = 0, posY = 0; GridAttribute gridAttribute = new GridAttribute(); foreach (XmlElement xmlElement in gridUnitInfo.ChildNodes) { switch (xmlElement.Name) { case ("PosX"): posX = Convert.ToInt32(xmlElement.InnerText); break; case ("PosY"): posY = Convert.ToInt32(xmlElement.InnerText); break; case ("Name"): gridAttribute.m_Name = Convert.ToString(xmlElement.InnerText); break; case ("Avoid"): gridAttribute.m_Avoid = Convert.ToSingle(xmlElement.InnerText); break; case ("Defense"): gridAttribute.m_Defense = Convert.ToSingle(xmlElement.InnerText); break; case ("Height"): gridAttribute.m_Height = Convert.ToSingle(xmlElement.InnerText); break; case ("MaxPassVolume"): gridAttribute.m_MaxPassVolume = Convert.ToSingle(xmlElement.InnerText); break; case ("CrossCost"): gridAttribute.m_CrossCost = Convert.ToSingle(xmlElement.InnerText); break; case ("GridType"): gridAttribute.SetGridType(Convert.ToString(xmlElement.InnerText)); break; } } GridUnit gridUnit = battleMap.mapGrids[posX - 1, posY - 1]; if (gridUnit == null) { gridUnit = new GridUnit(battleMap, posY - 1, posX - 1); battleMap.mapGrids[posX - 1, posY - 1] = gridUnit; } gridUnit.column = posX - 1; gridUnit.row = posY - 1; gridUnit.m_GridAttribute = gridAttribute; gridUnit.localPosition = new Vector3(posX * EGameConstL.Map_GridWidth, -posY * EGameConstL.Map_GridOffsetY, 0); if (gridUnit.m_GridAttribute.m_GridType == GridType.Normal) { battleMap.normalGrids.Add(gridUnit); } else if (gridUnit.m_GridAttribute.m_GridType == GridType.Obstacle) { battleMap.obstacleGrids.Add(gridUnit); } } return(battleMap); }