/// <summary> /// 方法:寻路算法 /// </summary> ///<param name="sg">起点</param> ///<param name="eg">终点</param> ///<param name="map">Map类的实例</param> ///<returns>PacGrid:返回路径起点</returns> internal PacGrid Find(PacGrid sg, PacGrid eg, PacMap map) { openList.Clear(); closeList.Clear(); openList.Add(sg); PacGrid g; int i = 0; while (!IsInList(eg.X, eg.Y, openList) || openList.Count == 0) { g = GetMinFFromList(openList); if (g != null) { openList.Remove(g); closeList.Add(g); CheckAround(g, eg, map); } else { return(g); } i++; } PacGrid tmpg = GetGridFromList(eg, openList); return(Save(tmpg)); }
/// <summary> /// 方法:追击寻路 /// </summary> private void Chase() { CurrentGrid = nextGrid; nextGrid = LookAt(CurrentGrid, PacmanGrid); //if (nextGrid.sunGrid != null) // nextGrid = nextGrid.sunGrid; }
/// <summary> /// 方法:逃跑寻路 /// </summary> private void Flee() { CurrentGrid = nextGrid; PacGrid gg = DodgePoint(CurrentGrid, PacmanGrid, SensingRange); nextGrid = LookAt(CurrentGrid, gg); //if (nextGrid.sunGrid != null) // nextGrid = nextGrid.sunGrid; }
/// <summary> /// 方法:怪物初始化 /// </summary> private void EnemyReset() { dest = BeginPoint.transform.position; dX = (int)dest.x; dY = (int)dest.y; nextGrid = new PacGrid() { X = dX, Y = dY }; }
/// <summary> /// 方法:寻找路径 /// </summary> /// <param name="sg">寻路起点</param> /// <param name="eg">寻路终点</param> /// <returns>PacGrid:返回路径的起点</returns> private PacGrid LookAt(PacGrid sg, PacGrid eg) { ClearPath(); sg.LandAttribute = 1; mapSample.StartGrid = sg; eg.LandAttribute = 1; mapSample.EndGrid = eg; //寻路 return(path.Find(mapSample.StartGrid, mapSample.EndGrid, mapSample)); }
/// <summary> /// 方法:对所有网格的地形属性进行初始化设置从而生成一张地图 /// </summary> ///<param name="grid">当前节点</param> ///<param name="landform">地形选项</param> internal void MapGridSet(PacGrid grid, byte landform) { if (landform > landTypes) { return; } else { grid.LandAttribute = landform; } }
/// <summary> /// 方法:从指定列表里获取指定节点 /// </summary> ///<param name="grid">节点</param> ///<param name="list">列表</param> /// <returns>Grid:返回指定节点</returns> protected PacGrid GetGridFromList(PacGrid grid, List <PacGrid> list) { foreach (PacGrid g in list) { if (g.X == grid.X && g.Y == grid.Y) { return(g); } } return(null); }
/// <summary> /// 方法:巡逻寻路 /// </summary> private void Patrol() { CurrentGrid = nextGrid; //if (nextGrid.sunGrid != null) // nextGrid = nextGrid.sunGrid; //else //{ PacGrid gg = PatrolTarget(CurrentGrid, PatrolRange); nextGrid = LookAt(CurrentGrid, gg); //} }
/// <summary> /// 方法:寻找巡逻范围内所有路径点 /// </summary> /// <param name="sg">当前位置</param> /// <param name="gripMap">网格路径图</param> /// <param name="range">范围</param> /// <returns>List PacGrid :路径点集合</returns> private List <PacGrid> isInRange(PacGrid sg, PacGrid[,] gripMap, int range) { List <PacGrid> gripPath = new List <PacGrid>(); foreach (PacGrid g in gripMap) { if (g.LandAttribute == 1 && GetDistance(sg, g) < range) { gripPath.Add(g); } } return(gripPath); }
/// <summary> /// 方法:保存路径 /// </summary> ///<param name="g">节点</param> internal PacGrid Save(PacGrid g) { PacGrid TransGrid; while (g.fatherGrid != null) { g.PathAttribute = true; TransGrid = g; g = g.fatherGrid; g.sunGrid = TransGrid; } return(g); }
/// <summary> /// 方法:巡逻范围内寻找躲避点 /// </summary> /// <param name="sg">当前位置</param> /// <param name="Target">目标位置</param> /// <param name="range">巡逻范围</param> /// <returns>PacGrid:躲避点</returns> private PacGrid DodgePoint(PacGrid sg, PacGrid Target, int range) { List <PacGrid> gripPath = isInRange(sg, gripMap, range); PacGrid rg = gripPath[0]; foreach (PacGrid g in gripPath) { if (GetDistance(Target, g) > GetDistance(Target, rg)) { rg = g; } } return(rg); }
/// <summary> /// 方法:计算G耗费 /// </summary> ///<param name="x">坐标x</param> ///<param name="y">坐标y</param> ///<param name="sg">起点</param> /// <returns>Int:G值</returns> protected int GetGridCostG(PacGrid CurrentGrid, PacGrid sg) { //if (CurrentGrid.fatherGrid != null) // return (sg.X == CurrentGrid.X || sg.Y == CurrentGrid.Y) ? CurrentGrid.fatherGrid.GCostAttribute + 10 : CurrentGrid.fatherGrid.GCostAttribute + 21; //else // return 0; if (CurrentGrid.fatherGrid != null) { return((sg.X == CurrentGrid.X || sg.Y == CurrentGrid.Y) ? sg.GCostAttribute + 10 : sg.GCostAttribute + 14); } else { return(0); } }
/// <summary> /// 构造方法:初始化地图 /// </summary> ///<param name="x">地图长</param> ///<param name="y">地图宽</param> public PacMap(int x, int y) { LenX = x; LenY = y; simpleMap = new PacGrid[LenX, LenY]; for (int i = 0; i < LenX; i++) { for (int j = 0; j < LenY; j++) { simpleMap[i, j] = new PacGrid() { X = i, Y = j }; } } }
/// <summary> /// 方法:从指定列表中获取F值最小的节点 /// </summary> ///<param name="list">列表</param> /// <returns>Grid:F值最小的节点</returns> protected PacGrid GetMinFFromList(List <PacGrid> list) { PacGrid rg = new PacGrid(); if (list.Count == 0) { return(null); } rg = list[0]; //int tmpF = list[0].GCostAttribute + list[0].HCostAttribute; foreach (PacGrid g in list) { if (g.GCostAttribute + g.HCostAttribute < rg.GCostAttribute + rg.HCostAttribute) { rg = g; } } return(rg); }
/// <summary> /// 方法:路径记忆清除 /// </summary> private void ClearPath() { PacGrid bg; while (nextGrid.sunGrid != null) { nextGrid = nextGrid.sunGrid; } while (nextGrid.fatherGrid != null) { bg = nextGrid; nextGrid = nextGrid.fatherGrid; bg.fatherGrid = null; } while (nextGrid.sunGrid != null) { bg = nextGrid; nextGrid = nextGrid.sunGrid; bg.sunGrid = null; } }
/// <summary> /// 方法:检查当前节点周边的节点 /// </summary> ///<param name="sg">当前节点</param> ///<param name="eg">终点</param> ///<param name="map">Map类的实例</param> protected void CheckAround(PacGrid sg, PacGrid eg, PacMap map) // { int gridmapRow = map.LenY; //获取地图的行数 int gridmapCol = map.LenX; //获取地图的列数 PacGrid[,] gridmap = map.simpleMap; for (int i = sg.X - 1; i < sg.X + 2; i++) { for (int j = sg.Y - 1; j < sg.Y + 2; j++) //筛选出相邻点 { if (i < 0 || i > gridmapCol - 1 || j < 0 || j > gridmapRow - 1) //若超出地图,pass { continue; } if (gridmap[i, j].LandAttribute == 0 || IsInList(i, j, closeList) || (i == sg.X && j == sg.Y))//若为障碍点/已考虑节点/当前点,pass { continue; } gridmap[i, j].HCostAttribute = GetGridCostH(i, j, eg); //计算H值(此节点到目标节点的移动损耗) if (!IsInList(i, j, openList)) //不在open列表,则加入 { openList.Add(gridmap[i, j]); //加入open列表 gridmap[i, j].fatherGrid = sg; //将此节点的父节点设为当前节点 gridmap[i, j].GCostAttribute = GetGridCostG(gridmap[i, j], sg); //计算G值(从起点到此节点的移动损耗) } else { int k = GetGridCostG(gridmap[i, j], sg); if (gridmap[i, j].GCostAttribute > k) //如果此节点经由当前节点离起点更近,则指向当前节点 { gridmap[i, j].GCostAttribute = k; //更新G值 gridmap[i, j].fatherGrid = sg; //更新父节点 } } } } }
/// <summary> /// 方法:计算H耗费 /// </summary> ///<param name="x">坐标x</param> ///<param name="y">坐标y</param> ///<param name="eg">终点</param> /// <returns>Int:H值</returns> protected int GetGridCostH(int x, int y, PacGrid eg) { return(Math.Abs(x - eg.X) + Math.Abs(y - eg.Y)); }
/// <summary> /// 方法:计算两个格子的路程 /// </summary> /// <param name="sg">起点</param> /// <param name="eg">终点</param> /// <returns>int:距离</returns> protected int GetDistance(PacGrid sg, PacGrid eg) { return((int)Math.Abs(sg.X - eg.X) + (int)Math.Abs(sg.Y - eg.Y)); }
/// <summary> /// 方法:固定频率执行 /// </summary> private void FixedUpdate() { if (transform.position != PacMan.transform.position && enemyStatus != EnemyStatus.Still) { if (isReset == false) { Vector2 temp = Vector2.MoveTowards(transform.position, dest, PacManSpeed); enemyRigidbody2d.MovePosition(temp); if ((Vector2)transform.position == dest) { if (dest.x == dX && dest.y == dY) { if (nextGrid.sunGrid != null) { nextGrid = nextGrid.sunGrid; } else { //PacGrid gg = PatrolTarget(nextGrid, PatrolRange); //nextGrid = LookAt(nextGrid, gg); CarryOut(enemyStatus); } dX = nextGrid.X; dY = nextGrid.Y; if (gripMap[dX, dY].LandAttribute != 0) { dest = new Vector2(dX, dY); } } if (isChase == true) { if (GetDistance(nextGrid, PacmanGrid) <= SensingRange) { enemyStatus = EnemyStatus.Chase; } else { enemyStatus = EnemyStatus.Patrol; } } } Vector2 dir = dest - (Vector2)transform.position; GetComponent <Animator>().SetFloat("DirX", dir.x); GetComponent <Animator>().SetFloat("DirY", dir.y); } else {//归元 isReset = false; EnemyReset(); } } PacmanGrid = new PacGrid() { X = (int)PacMan.transform.position.x, Y = (int)PacMan.transform.position.y }; if (LastEnemyStatus != enemyStatus) { CarryOut(enemyStatus); } LastEnemyStatus = enemyStatus; }
/// <summary> /// 方法:巡逻范围内随机寻点 /// </summary> /// <param name="sg">当前位置</param> /// <param name="range">巡逻范围</param> /// <returns>PacGrid:寻找到的随机点</returns> private PacGrid PatrolTarget(PacGrid sg, int range) { List <PacGrid> gripPath = isInRange(sg, gripMap, range); return(gripPath[UnityEngine.Random.Range(0, gripPath.Count) - 1]); }