public void GeneratePath(Point PointToMoveTo) { PathFinderFast p = new PathFinderFast(Area.PathGrid); p.Diagonals = true; p.Formula = Algorithms.HeuristicFormula.Manhattan; p.HeavyDiagonals = false; p.HeuristicEstimate = 2; p.PunishChangeDirection = false; p.TieBreaker = false; p.SearchLimit = 50000; Starttime = GameProject.GameLoop.GameTime; try { path = p.FindPath(Stats.Location.ToPoint(), PointToMoveTo); } catch (Exception ex) { throw new Exception("Error generating path for citizen " + ParentActor.ID.ToString() + ". Moving from point " + Stats.Location.X + "," + Stats.Location.Y + " to " + PointToMoveTo.X + "," + PointToMoveTo.Y + " in area " + Area.Width + "," + Area.Height, ex); } if (path != null) { double Rate = Stats.MovementSpeed; TimeToTarget = (path.Count - 1) / Rate; Starttime = GameProject.GameLoop.GameTime; } else { Console.WriteLine("Could not find a path for citizen " + ParentActor.ID.ToString()); } }
int tileSize; /**< Size of single tile */ #endregion Fields #region Constructors /// <summary> /// Constructor /// </summary> /// <param name="WS">Reference to World Screen</param> /// <param name="tileSize">Size of single tile</param> /// <param name="size">Size of map</param> public Map(WorldScreen WS, int tileSize, int size) { this.tileSize = tileSize; this.size = size; this.Entities = new List<Entity>(); PhysicalWorld = new World(new Vector2(0, 0)); Player = new Player(new Rectangle(6 * 64, 6 * 64, 64, 64), this); AddEntity(Player); chunk = new Chunk(new Rectangle(0, 0, size * tileSize, size * tileSize), this, tileSize); Parent = WS; pfinder = new PathFinderFast(GetChunk().GetCostArray()); for (int i = 0; i < 25; i++) { Rectangle r = new Rectangle((int)Helper.GetRandomTo(size * tileSize), (int)Helper.GetRandomTo(size * tileSize), 64, 64); Rectangle t = new Rectangle(r.X / tileSize, r.Y / tileSize, tileSize, tileSize); while (chunk.tiles[t.X,t.Y].isSolid) { r = new Rectangle((int)Helper.GetRandomTo(size * tileSize), (int)Helper.GetRandomTo(size * tileSize), 64, 64); t = new Rectangle(r.X / tileSize, r.Y / tileSize, tileSize, tileSize); } new ZombieBig(r, this); } new Barrel(new Rectangle(Player.Position.X + 64, Player.Position.Y + 64, 32, 32), this); new FloorFan(new Rectangle(Player.Position.X + 64, Player.Position.Y + 64, 128, 128), this); //chunk.Save("Content/Chunks/00.xml"); }
/// <summary> /// Constructor /// </summary> /// <param name="WS">Reference to World Screen</param> /// <param name="tileSize">Size of single tile</param> /// <param name="size">Size of map</param> public Map(WorldScreen WS, int tileSize, int size) { this.tileSize = tileSize; this.size = size; this.Entities = new List <Entity>(); PhysicalWorld = new World(new Vector2(0, 0)); Player = new Player(new Rectangle(6 * 64, 6 * 64, 64, 64), this); AddEntity(Player); chunk = new Chunk(new Rectangle(0, 0, size * tileSize, size * tileSize), this, tileSize); Parent = WS; pfinder = new PathFinderFast(GetChunk().GetCostArray()); for (int i = 0; i < 25; i++) { Rectangle r = new Rectangle((int)Helper.GetRandomTo(size * tileSize), (int)Helper.GetRandomTo(size * tileSize), 64, 64); Rectangle t = new Rectangle(r.X / tileSize, r.Y / tileSize, tileSize, tileSize); while (chunk.tiles[t.X, t.Y].isSolid) { r = new Rectangle((int)Helper.GetRandomTo(size * tileSize), (int)Helper.GetRandomTo(size * tileSize), 64, 64); t = new Rectangle(r.X / tileSize, r.Y / tileSize, tileSize, tileSize); } new ZombieBig(r, this); } new Barrel(new Rectangle(Player.Position.X + 64, Player.Position.Y + 64, 32, 32), this); new FloorFan(new Rectangle(Player.Position.X + 64, Player.Position.Y + 64, 128, 128), this); //chunk.Save("Content/Chunks/00.xml"); }
public bool checkWalk(int startX, int startY, int targetX, int targetY) { if (startX == door_x && startY == door_y) { return(true); } else { if ((!(targetX == door_x && targetY == door_y)) && targetX >= 0 && targetY >= 0 && targetX < breed && targetY < lang) { PathFinderFast Pathfinder = new PathFinderFast(GenerateGrid(targetX, targetY)); List <PathFinderNode> Path = Pathfinder.FindPath(new Point(startX, startY), new Point(targetX, targetY)); if (Path == null || Path.Count == 0) { return(false); } else { return(true); } } else { return(false); } } }
private void DoPath(Map map, Unit unit, Vec2Double target) { var pathF = new PathFinderFast(map.MGrid, map); _path = pathF.FindPath(new Vector2I((int)unit.Position.X, (int)unit.Position.Y), new Vector2I((int)target.X, (int)target.Y), 1, 2, 5, 10); _path?.Reverse(); _i = 0; _pathLength = 0; }
public static List <int[]> FindPath(Point startPoint, Point endPoint, int mapCode) { GameMap gameMap = GameManager.MapMgr.DictMaps[mapCode]; List <int[]> result; if (null == gameMap) { result = null; } else { PathFinderFast pathFinderFast; if (GlobalNew._pathStack.Count <= 0) { pathFinderFast = new PathFinderFast(gameMap.MyNodeGrid.GetFixedObstruction()) { Formula = HeuristicFormula.Manhattan, Diagonals = true, HeuristicEstimate = 2, ReopenCloseNodes = true, SearchLimit = int.MaxValue, Punish = null, MaxNum = Global.GMax(gameMap.MapGridWidth, gameMap.MapGridHeight) }; } else { pathFinderFast = GlobalNew._pathStack.Pop(); } startPoint.X = (double)(gameMap.CorrectWidthPointToGridPoint((int)startPoint.X) / gameMap.MapGridWidth); startPoint.Y = (double)(gameMap.CorrectHeightPointToGridPoint((int)startPoint.Y) / gameMap.MapGridHeight); endPoint.X = (double)(gameMap.CorrectWidthPointToGridPoint((int)endPoint.X) / gameMap.MapGridWidth); endPoint.Y = (double)(gameMap.CorrectHeightPointToGridPoint((int)endPoint.Y) / gameMap.MapGridHeight); pathFinderFast.EnablePunish = false; List <PathFinderNode> nodeList = pathFinderFast.FindPath(startPoint, endPoint); if (nodeList == null || nodeList.Count <= 0) { result = null; } else { List <int[]> path = new List <int[]>(); for (int i = 0; i < nodeList.Count; i++) { path.Add(new int[] { nodeList[i].X, nodeList[i].Y }); } result = path; } } return(result); }
public BattleData(Squad[] enemyArmy, Squad[] allyArmy, byte[] map, int mapWidth) { this.EnemyArmy = enemyArmy; this.AllyArmy = allyArmy; this.Map = map; this.MapWidth = mapWidth; this.MapHeight = map.Length / mapWidth; this.MapHeightLog2 = (int)(Math.Log(MapWidth, 2)); this.PathFinder = new PathFinderFast(Map, MapWidth); PathFinder.PathFinderDebug += PathFinder_PathFinderDebug; }
public List <Node> GetPath(float X, float Z, int id) { List <Node> ReturnPath = new List <Node>(); var Temp = GetWaypointClosestTo(Character.Api.Player.X, Character.Api.Player.Z); int StartingX = Convert.ToInt32(Temp.X) + offset; int StartingZ = Convert.ToInt32(Temp.Z) + offset; int DestinationX = Convert.ToInt32(X) + offset; int DestinationZ = Convert.ToInt32(Z) + offset; var mob = Character.Api.Entity.GetEntity(id); List <PathFinderNode> Path = new PathFinderFast(Grid).FindPath(new DeenGames.Utils.Point(StartingX, StartingZ), new DeenGames.Utils.Point(DestinationX, DestinationZ)); if (Path != null && Path.Count > 5) { foreach (PathFinderNode point in Path) { ReturnPath.Add(new Node { X = point.X - offset, Z = point.Y - offset }); } // Waypoints are added backwards, so let's reverse. ReturnPath.Reverse(); // Character.Logger.AddDebugText(Character.Tc.rtbDebug, string.Format(@"Path Found // Moving to {0} distance {1}y", // Character.Api.Entity.GetEntity(Character.hunter.MobID).Name, Character.Api.Entity.GetEntity(Character.hunter.MobID).Distance)); ReturnPath = SmoothNodes(ReturnPath); Character.Api.ThirdParty.KeyDown(EliteMMO.API.Keys.NUMPAD8); Thread.Sleep(1); Character.Api.ThirdParty.KeyUp(EliteMMO.API.Keys.NUMPAD8); Thread.Sleep(1); FailedToPath = 0; } if (Path == null || Path.Count < 5) { FailedToPath++; Character.Logger.AddDebugText(Character.Tc.rtbDebug, string.Format(@"Failed To Find Path to {0} distance // {1}y", mob.Name.ToString(), mob.Distance.ToString())); } if (FailedToPath > 2) { Character.Target.BlockedTargets.Add(id); Character.Logger.AddDebugText(Character.Tc.rtbDebug, string.Format(@"failed to path to many times. added {0} id {1} to blocked target list", mob.Name, id.ToString())); } return(ReturnPath); }
public void InitPathFinder() { mPathFinder = new PathFinderFast(this); //EuclideanNoSQR seemed to work the best, although it sometimes provides a little hop off ledges that is unneeded mPathFinder.Formula = HeuristicFormula.EuclideanNoSQR; //if false then diagonal movement will be prohibited mPathFinder.Diagonals = false; //if true then diagonal movement will have higher cost mPathFinder.HeavyDiagonals = false; //estimate of path length mPathFinder.HeuristicEstimate = 6; mPathFinder.PunishChangeDirection = false; mPathFinder.TieBreaker = false; mPathFinder.SearchLimit = 10000; mPathFinder.DebugProgress = false; mPathFinder.DebugFoundPath = false; }
public void CalcMinionNewPath(MinionBase minion, Cell cell) { if (false) { minion.Path = PathFinding.CalcPath(minion.CurrentCell, cell, true, 10f); minion.PathLength = (minion.Path.Count - 1) * Map.R; minion.TraveledLength = 0f; } else { IPathFinder mPathFinder = new PathFinderFast(Map.Matrix); //IPathFinder mPathFinder = new PathFinder(Map.Matrix); mPathFinder.Formula = HeuristicFormula.Manhattan; mPathFinder.Diagonals = false; mPathFinder.HeavyDiagonals = false; mPathFinder.HeuristicEstimate = 1; mPathFinder.PunishChangeDirection = false; mPathFinder.TieBreaker = false; mPathFinder.SearchLimit = 5000; mPathFinder.DebugProgress = true; mPathFinder.DebugFoundPath = true; List<PathFinderNode> path = mPathFinder.FindPath(new System.Drawing.Point(minion.CurrentCell.Coord.X - 1, minion.CurrentCell.Coord.Y - 1), new System.Drawing.Point(cell.Coord.X - 1, cell.Coord.Y - 1)); minion.Path = new List<int>(); if (path != null) { path.Reverse(); for (int i = 0; i < path.Count; i++) { minion.Path.Add(path[i].X + path[i].Y * Map.Width); } } minion.PathLength = (minion.Path.Count - 1) * Map.R; minion.TraveledLength = 0f; } }
public List <CSCell> Search(Vector3 startPos, Vector3 endPos) { List <CSCell> ret = new List <CSCell>(); PathFinderFast PathFinder = new PathFinderFast(m_map); PathFinder.Formula = HeuristicFormula.Manhattan; //使用我个人觉得最快的曼哈顿A*算法 PathFinder.SearchLimit = 2000; //即移动经过方块(20*20)不大于2000个(简单理解就是步数) Point2D Start = new Point2D((int)startPos.x, (int)startPos.y); Point2D End = new Point2D((int)endPos.x, (int)endPos.y); List <PathFinderNode> path = PathFinder.FindPath(Start, End); //开始寻径 if (path == null) { Debug.Log("路径不存在!"); } else { string output = string.Empty; for (int i = path.Count - 1; i >= 0; i--) { output = string.Format(output + "{0}" + path[i].X.ToString() + "{1}" + path[i].Y.ToString() + "{2}", "(", ",", ") "); ret.Add(new CSCell() { X = path[i].X, Y = path[i].Y, Value = (int)MapCellStatus.Normal }); } Debug.Log("路径坐标分别为:" + output); } return(ret); }
/// <summary> /// Analyses the map. Can take up a few seconds. /// </summary> public void Analyse() { DateTime now = DateTime.Now; Width = Game.MapWidth; Height = Game.MapHeight; int minSize = Math.Max(Width, Height); int power = 1; while (power < minSize) { power *= 2; } PathFinderTileData = new byte[power, power]; PathFinderTile = new PathFinderFast(PathFinderTileData); BuildGrid = new BuildTileInfo[Width, Height]; WalkGrid = new WalkTileInfo[Width * 4, Height * 4]; UpdateWalkability(); CalculateInaccessibility(); CalculateAltitude(); InitLength = (DateTime.Now.Ticks - now.Ticks) / 10000.0f; FindBases(); #if DEBUG Game.SendText($"Map analyser: {InitLength}ms"); SaveToFile(Game.MapFileName); #endif SelfBase = Bases.OrderBy(x => x.DepotPosition.CalcDistance(Game.Self.StartLocation)).First(); AnalysisFinished(); }
void ComputeRouteMatrix(TERRAIN_CAPABILITY terrainCapability, float minAltitude, float maxAltitude) { bool computeMatrix = false; byte thisMatrix = 1; // prepare matrix if (earthRouteMatrix == null) { earthRouteMatrix = new byte[EARTH_ROUTE_SPACE_WIDTH * EARTH_ROUTE_SPACE_HEIGHT]; computedMatrixBits = 0; } // prepare water mask data bool checkWater = terrainCapability != TERRAIN_CAPABILITY.Any; if (checkWater) { computeMatrix = CheckRouteWaterMask(); } // check elevation data if needed bool checkElevation = minAltitude > 0f || maxAltitude < 1.0f; if (checkElevation) { if (viewportElevationPoints == null) { Debug.LogError("Viewport needs to be initialized before calling using Path Finding functions."); return; } if (minAltitude != earthRouteMatrixWithElevationMinAltitude || maxAltitude != earthRouteMatrixWithElevationMaxAltitude) { computeMatrix = true; earthRouteMatrixWithElevationMinAltitude = minAltitude; earthRouteMatrixWithElevationMaxAltitude = maxAltitude; } } else { if (terrainCapability == TERRAIN_CAPABILITY.OnlyGround) { thisMatrix = 2; } else { thisMatrix = 4; // water } if ((computedMatrixBits & thisMatrix) == 0) { computeMatrix = true; computedMatrixBits |= thisMatrix; // mark computedMatrixBits } } // Compute route if (computeMatrix) { int jj_waterMask = 0, kk_waterMask; int jj_terrainElevation = 0, kk_terrainElevation; bool dry = false; float elev = 0; for (int j = 0; j < EARTH_ROUTE_SPACE_HEIGHT; j++) { int jj = j * EARTH_ROUTE_SPACE_WIDTH; if (checkWater) { jj_waterMask = (int)((j * (float)earthWaterMaskHeight / EARTH_ROUTE_SPACE_HEIGHT)) * earthWaterMaskWidth; } if (checkElevation) { jj_terrainElevation = ((int)(j * (float)heightmapTextureHeight / EARTH_ROUTE_SPACE_HEIGHT)) * heightmapTextureWidth; } for (int k = 0; k < EARTH_ROUTE_SPACE_WIDTH; k++) { bool setBit = false; // Check altitude if (checkElevation) { kk_terrainElevation = (int)(k * (float)heightmapTextureWidth / EARTH_ROUTE_SPACE_WIDTH); elev = viewportElevationPoints[jj_terrainElevation + kk_terrainElevation]; } if (elev >= minAltitude && elev <= maxAltitude) { if (checkWater) { kk_waterMask = (int)(k * (float)earthWaterMaskWidth / EARTH_ROUTE_SPACE_WIDTH); dry = !earthWaterMask.GetBit(jj_waterMask + kk_waterMask); } if (terrainCapability == TERRAIN_CAPABILITY.Any || terrainCapability == TERRAIN_CAPABILITY.OnlyGround && dry || terrainCapability == TERRAIN_CAPABILITY.OnlyWater && !dry) { setBit = true; } } if (setBit) // set navigation bit { earthRouteMatrix[jj + k] |= thisMatrix; } else // clear navigation bit { earthRouteMatrix[jj + k] &= (byte)(byte.MaxValue ^ thisMatrix); } } } } if (finder == null) { if (_customRouteMatrix == null || !_pathFindingEnableCustomRouteMatrix) { PathFindingCustomRouteMatrixReset(); } finder = new PathFinderFast(earthRouteMatrix, thisMatrix, EARTH_ROUTE_SPACE_WIDTH, EARTH_ROUTE_SPACE_HEIGHT, _customRouteMatrix); } else { if (computeMatrix || thisMatrix != lastMatrix) { lastMatrix = thisMatrix; finder.SetCalcMatrix(earthRouteMatrix, thisMatrix); } } }
/// <summary> /// 从当前位置向目标位置移动 /// </summary> /// <param name="destination">窗口Canvas中的目标位置</param> public void MoveTo(Point destination) { if (isActionLock || isFreeze || isPetrifaction || isSpecialMove) { return; } //特殊坐标判断处理 Point end = terrain.GetCoordinateFromPosition(destination); int startX = (int)Coordinate.X, startY = (int)Coordinate.Y, endX = (int)end.X, endY = (int)end.Y; if ((startX == endX && startY == endY) || !terrain.InEffectiveRange(end)) { return; } //对目标点进行有效检测 bool findObstacle = false; //如果在地面则采用路径预测法中的(两点线段检测(直线等分逐测算法)+A*寻路算法组合),空中目前忽略一切障碍物 if (SpaceLayer == SpaceLayers.Ground) { //if (terrain.TerrainType == TerrainTypes.Static) { double angle = GlobalMethod.GetRadian(Position, destination); double cosA = Math.Cos(angle); double sinA = Math.Sin(angle); for (int i = 0; i <= (int)(GlobalMethod.GetDistance(Position, destination) / terrain.UnitMinLength); i++) { Point p = terrain.GetCoordinateFromPosition(new Point(cosA * i * terrain.UnitMinLength + destination.X, sinA * i * terrain.UnitMinLength + destination.Y)); if (terrain.DynamicMatrix[(int)p.X, (int)p.Y] == 0) { findObstacle = true; break; } } //} else if (terrain.TerrainType == TerrainTypes.Dynamic) { // //动态地形直接用寻路移动模式 // findObstacle = true; //} } //如果将要的行程中有障碍则寻路移动,否则直线移动 if (findObstacle) { PathFinderFast pathFinderFast = new PathFinderFast(terrain.DynamicMatrix) { Formula = HeuristicFormula.Manhattan, Diagonals = true, HeuristicEstimate = 2, SearchLimit = (int)Application.Current.Host.Content.ActualWidth, //寻径限度(太小可能导致找不到路径) }; List<PathFinderNode> pathTemp = pathFinderFast.FindPath(new Point2D(startX, startY), new Point2D(endX, endY)); if (pathTemp != null && pathTemp.Count > 1) { path = pathTemp; path.Remove(path[path.Count - 1]); StraightMoveTo(new Point(path[path.Count - 1].X, path[path.Count - 1].Y)); } } else { path.Clear(); path.Add(new PathFinderNode() { X = endX, Y = endY }); StraightMoveTo(end); } }
/// <summary>Find a path from a point on a map to another point</summary> /// <returns>Point[] of path</returns> public static Point[] GetPathFast(gMap Map, int X, int Y, int EndX, int EndY) { int NewWidth = (int)Math.Pow(2d, Math.Ceiling(Math.Log(Map.Width) / Math.Log(2d))); int NewHeight = (int)Math.Pow(2d, Math.Ceiling(Math.Log(Map.Height) / Math.Log(2d))); byte[,] Grid = new byte[NewWidth, NewHeight]; Grid.Initialize(); for (int x = 0; x < Map.Width; x++) { for (int y = 0; y < Map.Height; y++) { Grid[x, y] = Convert.ToByte(Map[x, y]); } } PathFinderFast PathFinder = new PathFinderFast(Grid); PathFinder.Formula = HeuristicFormula.Manhattan; PathFinder.Diagonals = true; PathFinder.HeavyDiagonals = false; PathFinder.HeuristicEstimate = 2; PathFinder.PunishChangeDirection = false; PathFinder.TieBreaker = false; PathFinder.SearchLimit = 50000; PathFinder.DebugProgress = false; PathFinder.ReopenCloseNodes = true; PathFinder.DebugFoundPath = true; List<PathFinderNode> path = PathFinder.FindPath(new Point(X, Y), new Point(EndX, EndY)); Point[] pointArray = new Point[path.Count]; for (int i = 0; i < pointArray.Length; i++) { pointArray[(pointArray.Length - i) - 1] = new Point(path[i].X, path[i].Y); } return pointArray; }
/// <summary> /// Given a list of potential molecules, weed out all the ones where /// the atoms are not all adjacent to each other. This can occur due /// to a bug-fix for I-shaped molecules not reacting, where we /// extended molecule detection to all non-empty adjacent tiles. /// As a result, you can have H-Be-Cl forming H-Cl, which is wrong. /// This function will fix that, by checking that H and Cl are adjacent. /// </summary> /// <param name="molecules"></param> /// <returns></returns> private IList<Molecule> weedOutNonConnectedMolecules(IList<Molecule> molecules) { IList<Molecule> toReturn = new List<Molecule>(); // The solution to this is really stupid. Checking for adjacencies // won't work; that will allow H-H-Be-Cl-Cl to form H-H-Cl-Cl, because // the two Hs are adjacent, as are the two Cls. Lame, dude. // The solution? Use path-finding to make sure there's a solid path of // atoms connecting every atom to every other atom. Yech. // Multi-Threading is a bloody business. There are lots of casualties. // Remove said casualties -- molecules that have "NONE" atoms in them. molecules = molecules.Where(m => !m.AtomTiles.Any(t => t.Atom == Atom.NONE)).ToList(); foreach (Molecule candidate in molecules) { this._pathFinder = new PathFinderFast(candidate.ByteGrid); _pathFinder.Diagonals = false; bool allPairsHaveAPath = true; List<PathFinderNode> path; Tile startTile; Tile endTile; Point start; Point end; for (int i = 0; i < candidate.AtomTiles.Count; i++) { startTile = candidate.AtomTiles[i]; start = new Point(startTile.X, startTile.Y); for (int j = i + 1; j < candidate.AtomTiles.Count; j++) { endTile = candidate.AtomTiles[j]; end = new Point(endTile.X, endTile.Y); path = this._pathFinder.FindPath(start, end); if (path == null) { allPairsHaveAPath = false; } } } if (allPairsHaveAPath == true) { toReturn.Add(candidate); } } return toReturn; }
public void DoEvents() { while (true) { StringBuilder sendText = new StringBuilder(); foreach (ConnectedUser user in _Users.Values) { if (user._Room_X != user._Room_X_Target || user._Room_Y != user._Room_Y_Target) { int[] nextCoords; bool walkDoor = false; if (user._Room_X == door_x && user._Room_Y == door_y) { // first walk out of the door, then check if you can walk after that! walkDoor = true; if (user._Room_X_Target == doorstep_x && user._Room_Y_Target == doorstep_y) { // just come out of the door squareState[,] stateMap = avatarStateMap(doorstep_x, doorstep_y); if (stateMap[doorstep_x, doorstep_y] == squareState.Open && (!_sqUnit[doorstep_x, doorstep_y])) { // doorstep is free nextCoords = new int[2]; nextCoords[0] = doorstep_x; nextCoords[1] = doorstep_y; } else { nextCoords = null; } } else { PathFinderFast Pathfinder = new PathFinderFast(GenerateGrid(user._Room_X_Target, user._Room_Y_Target)); List<PathFinderNode> Path = Pathfinder.FindPath(new Point(doorstep_x, doorstep_y), new Point(user._Room_X_Target, user._Room_Y_Target)); if (Path == null || Path.Count == 0) { nextCoords = null; } else { // after coming out of your door you'll be able to walk squareState[,] stateMap = avatarStateMap(doorstep_x, doorstep_y); if (stateMap[doorstep_x, doorstep_y] == squareState.Open && (!_sqUnit[doorstep_x, doorstep_y])) { // doorstep is free nextCoords = new int[2]; nextCoords[0] = doorstep_x; nextCoords[1] = doorstep_y; } else { nextCoords = null; } } } } else { PathFinderFast Pathfinder = new PathFinderFast(GenerateGrid(user._Room_X_Target, user._Room_Y_Target)); List<PathFinderNode> Path = Pathfinder.FindPath(new Point(user._Room_X, user._Room_Y), new Point(user._Room_X_Target, user._Room_Y_Target)); if (Path == null || Path.Count == 0) { nextCoords = null; } else { PathFinderNode NextPosition = Path[Path.Count - 2]; nextCoords = new int[2]; nextCoords[0] = NextPosition.X; nextCoords[1] = NextPosition.Y; } } if (nextCoords == null) { user._Room_Sit = ""; user._Room_X_Target = user._Room_X; user._Room_Y_Target = user._Room_Y; StopAvatarPacket stopMove = new StopAvatarPacket(); stopMove.I = user._UserID; string stopMovePacket = JsonConvert.SerializeObject(stopMove); sendText.Append("064"); sendText.Append(stopMovePacket); sendText.Append("#"); } else { int nextX = nextCoords[0]; int nextY = nextCoords[1]; squareState nextState = _sqState[nextX, nextY]; if (!walkDoor) { _sqUnit[user._Room_X, user._Room_Y] = false; } _sqUnit[nextX, nextY] = true; double nextHeight = 0; nextHeight = (double)_sqHeight[nextX, nextY]; // dir eerst! user._Room_Dir = getNewDir(user._Room_X, user._Room_Y, nextX, nextY); user._Room_X = nextX; user._Room_Y = nextY; user._Room_Z = (int)nextHeight; if (nextState == squareState.Seat) { // Do Sit MoveAvatarPacket mvpack = new MoveAvatarPacket(); mvpack.I = user._UserID; mvpack.X = nextX; mvpack.Y = nextY; mvpack.H = user._Room_Dir; string stringmvpack = JsonConvert.SerializeObject(mvpack); sendText.Append("057"); sendText.Append(stringmvpack); sendText.Append("#"); if (user._Room_X == user._Room_X_Target && user._Room_Y == user._Room_Y_Target) { user._Room_Dir = _sqRot[user._Room_X, user._Room_Y] * 2; user._Room_Sit = user._Room_Dir.ToString() + "|" + _sqTile[user._Room_X, user._Room_Y]; StopAvatarPacket stopMove = new StopAvatarPacket(); stopMove.I = user._UserID; string stopMovePacket = JsonConvert.SerializeObject(stopMove); sendText.Append("064"); sendText.Append(stopMovePacket); sendText.Append("#"); SetSitPacket setSit = new SetSitPacket(); setSit.I = user._UserID; setSit.S = user._Room_Sit; string SetSitPacket = JsonConvert.SerializeObject(setSit); sendText.Append("081"); sendText.Append(SetSitPacket); sendText.Append("#"); } } else { user._Room_Sit = ""; MoveAvatarPacket mvpack = new MoveAvatarPacket(); mvpack.I = user._UserID; mvpack.X = nextX; mvpack.Y = nextY; mvpack.H = user._Room_Dir; string stringmvpack = JsonConvert.SerializeObject(mvpack); sendText.Append("057"); sendText.Append(stringmvpack); sendText.Append("#"); if (user._Room_X == user._Room_X_Target && user._Room_Y == user._Room_Y_Target) { StopAvatarPacket stopMove = new StopAvatarPacket(); stopMove.I = user._UserID; string stopMovePacket = JsonConvert.SerializeObject(stopMove); sendText.Append("064"); sendText.Append(stopMovePacket); sendText.Append("#"); } } } } } // BOTS try { foreach (RoomBot bot in _Bots.Values) { if (bot._MyX != bot.targetX || bot._MyY != bot.targetY) { int[] nextCoords; bool walkDoor = false; if (bot._MyX == door_x && bot._MyY == door_y) { // first walk out of the door, then check if you can walk after that! walkDoor = true; if (bot.targetX == doorstep_x && bot.targetY == doorstep_y) { // just come out of the door squareState[,] stateMap = avatarStateMap(doorstep_x, doorstep_y); if (stateMap[doorstep_x, doorstep_y] == squareState.Open && (!_sqUnit[doorstep_x, doorstep_y])) { // doorstep is free nextCoords = new int[2]; nextCoords[0] = doorstep_x; nextCoords[1] = doorstep_y; } else { nextCoords = null; } } else { PathFinderFast Pathfinder = new PathFinderFast(GenerateGrid(bot.targetX, bot.targetY)); List<PathFinderNode> Path = Pathfinder.FindPath(new Point(doorstep_x, doorstep_y), new Point(bot.targetX, bot.targetY)); if (Path == null || Path.Count == 0) { nextCoords = null; } else { // after coming out of your door you'll be able to walk squareState[,] stateMap = avatarStateMap(doorstep_x, doorstep_y); if (stateMap[doorstep_x, doorstep_y] == squareState.Open && (!_sqUnit[doorstep_x, doorstep_y])) { // doorstep is free nextCoords = new int[2]; nextCoords[0] = doorstep_x; nextCoords[1] = doorstep_y; } else { nextCoords = null; } } } } else { PathFinderFast Pathfinder = new PathFinderFast(GenerateGrid(bot.targetX, bot.targetY)); List<PathFinderNode> Path = Pathfinder.FindPath(new Point(bot._MyX, bot._MyY), new Point(bot.targetX, bot.targetY)); if (Path == null || Path.Count == 0) { nextCoords = null; } else { PathFinderNode NextPosition = Path[Path.Count - 2]; nextCoords = new int[2]; nextCoords[0] = NextPosition.X; nextCoords[1] = NextPosition.Y; } } if (nextCoords == null) { if (bot.walking) { bot._Sit = ""; bot.targetX = bot._MyX; bot.targetY = bot._MyY; StopAvatarPacket stopMove = new StopAvatarPacket(); stopMove.I = bot._MyAvatarID; string stopMovePacket = JsonConvert.SerializeObject(stopMove); sendText.Append("064"); sendText.Append(stopMovePacket); sendText.Append("#"); bot.walking = false; } } else { bot.walking = true; int nextX = nextCoords[0]; int nextY = nextCoords[1]; squareState nextState = _sqState[nextX, nextY]; if (!walkDoor) { _sqUnit[bot._MyX, bot._MyY] = false; } _sqUnit[nextX, nextY] = true; double nextHeight = 0; nextHeight = (double)_sqHeight[nextX, nextY]; bot._MyZ = getNewDir(bot._MyX, bot._MyY, nextX, nextY); bot._MyX = nextX; bot._MyY = nextY; //bot._MyZ = (int)nextHeight; if (nextState == squareState.Seat) { // Do Sit MoveAvatarPacket mvpack = new MoveAvatarPacket(); mvpack.I = bot._MyAvatarID; mvpack.X = nextX; mvpack.Y = nextY; mvpack.H = bot._MyZ; string stringmvpack = JsonConvert.SerializeObject(mvpack); sendText.Append("057"); sendText.Append(stringmvpack); sendText.Append("#"); if (bot._MyX == bot.targetX && bot._MyY == bot.targetY) { bot._MyZ = _sqRot[bot._MyX, bot._MyY] * 2; bot._Sit = bot._MyZ.ToString() + "|" + _sqTile[bot._MyX, bot._MyY]; StopAvatarPacket stopMove = new StopAvatarPacket(); stopMove.I = bot._MyAvatarID; string stopMovePacket = JsonConvert.SerializeObject(stopMove); sendText.Append("064"); sendText.Append(stopMovePacket); sendText.Append("#"); SetSitPacket setSit = new SetSitPacket(); setSit.I = bot._MyAvatarID; setSit.S = bot._Sit; string SetSitPacket = JsonConvert.SerializeObject(setSit); sendText.Append("081"); sendText.Append(SetSitPacket); sendText.Append("#"); } } else { bot._Sit = ""; MoveAvatarPacket mvpack = new MoveAvatarPacket(); mvpack.I = bot._MyAvatarID; mvpack.X = nextX; mvpack.Y = nextY; mvpack.H = bot._MyZ; string stringmvpack = JsonConvert.SerializeObject(mvpack); sendText.Append("057"); sendText.Append(stringmvpack); sendText.Append("#"); if (bot._MyX == bot.targetX && bot._MyY == bot.targetY) { StopAvatarPacket stopMove = new StopAvatarPacket(); stopMove.I = bot._MyAvatarID; string stopMovePacket = JsonConvert.SerializeObject(stopMove); sendText.Append("064"); sendText.Append(stopMovePacket); sendText.Append("#"); bot.walking = false; } } } } } } catch (Exception e) { Console.WriteLine("BOTWALK ERROR: {0}", e); } string sendTextString = sendText.ToString(); if (sendTextString != "") { foreach (ConnectedUser usr in _Users.Values) { usr.sendData(sendTextString); } } Thread.Sleep(480); // 480 milliseconds } }
public PathFindingAdapter(Map map) { _map = map; _grid = new byte[_map.Width, _map.Height]; _adaptee = new PathFinderFast(_grid); }
/// <summary> /// Creates the shortest route between two points, used in Move() /// </summary> private void Path(Vector3I targetPosition) { //create a grid with all blocks in the 2d plane byte[,] grid = new byte[World.Map.Width, World.Map.Length]; PathFinder pathFinder; Vector3I botPos = Position.ToBlockCoords(); //Loop through all XZ coordinates of the map for (int y = 0; y < World.Map.Length; y++) { for (int x = 0; x < World.Map.Width; x++) { //Find all valid positions, set as either an available tile or blocked tile if (ValidBlock(new Vector3I(x, y, botPos.Z)) && ValidBlock(new Vector3I(x, y, botPos.Z - 1))) { grid[x, y] = PathFinderHelper.EMPTY_TILE; } else { grid[x, y] = PathFinderHelper.BLOCKED_TILE; } } } //set pathFinder to the grid just created, disallow diagonals pathFinder = new PathFinder(grid); pathFinder.Diagonals = false; pathFinder.PunishChangeDirection = false; Point botInitPoint = new Point(botPos.X, botPos.Y); Point botFinalPoint = new Point(NewPosition.ToBlockCoords().X, NewPosition.ToBlockCoords().Y); //Implement A* to determine optimal path between two spots List<PathFinderNode> path = new PathFinderFast(grid).FindPath(botInitPoint, botFinalPoint); if (path == null) { //There is no path, stop moving beganMoving = false; isMoving = false; return; } //Convert node to block positions foreach(PathFinderNode node in path) { PositionList.Add(new Vector3I(node.X, node.Y, botPos.Z)); } //A* returns points in the opposite order needed, reverse in order to get proper order PositionList.Reverse(); }
public List<PathFinderNode> buildPath(System.Drawing.Point Start) { List<PathFinderNode> path; var pather = new PathFinderFast(grid); pather.Diagonals = false; foreach (var dest in this.Dests) { path = pather.FindPath(Start, dest); if (path != null) return path; } return null; }
public void InitPathFinder() { mPathFinder = new PathFinderFast(mGrid, this); mPathFinder.Formula = HeuristicFormula.Manhattan; //if false then diagonal movement will be prohibited mPathFinder.Diagonals = false; //if true then diagonal movement will have higher cost mPathFinder.HeavyDiagonals = false; //estimate of path length mPathFinder.HeuristicEstimate = 6; mPathFinder.PunishChangeDirection = false; mPathFinder.TieBreaker = false; mPathFinder.SearchLimit = 1000000; mPathFinder.DebugProgress = false; mPathFinder.DebugFoundPath = false; }
public bool checkWalk(int startX, int startY, int targetX, int targetY) { if (startX == door_x && startY == door_y) { return true; } else { if ((!(targetX == door_x && targetY == door_y)) && targetX >= 0 && targetY >= 0 && targetX < breed && targetY < lang) { PathFinderFast Pathfinder = new PathFinderFast(GenerateGrid(targetX, targetY)); List<PathFinderNode> Path = Pathfinder.FindPath(new Point(startX, startY), new Point(targetX, targetY)); if (Path == null || Path.Count == 0) { return false; } else { return true; } } else { return false; } } }
/// <summary> /// 向目标点跑去 /// </summary> /// <param name="destination">目标点(窗口坐标系)</param> public void RunTo(Point destination) { if (isActionLocked) { return; } //特殊坐标判断处理 Point end = Scene.GetGameCoordinate(destination); if ((int)Coordinate.X == end.X && (int)Coordinate.Y == end.Y) { return; } //目的地是自己脚底则取消移动 if (end.X < 0 || end.Y < 0 || end.X > Scene.TerrainMatrix.GetUpperBound(0) || end.Y > Scene.TerrainMatrix.GetUpperBound(0)) { return; } //目的地超出坐标系范围 //采用路径预测法中的(两点线段检测(直线等分逐测算法)+A*寻路算法组合) bool findObstacle = false; Point start = Scene.GetWindowCoordinate(Coordinate); double angle = Global.GetRadian(start, destination); int detectNum = (int)(Global.GetDistance(start, destination)); for (int i = 0; i <= detectNum; i++) { int x = (int)(Math.Cos(angle) * i + destination.X); int y = (int)(Math.Sin(angle) * i + destination.Y); Point p = Scene.GetGameCoordinate(new Point(x, y)); if (Scene.DynamicMatrix[(int)p.X, (int)p.Y] == 0) { findObstacle = true; break; } } if (findObstacle) { PathFinderFast pathFinderFast = new PathFinderFast(Scene.DynamicMatrix) { Formula = HeuristicFormula.Manhattan, Diagonals = true, HeuristicEstimate = 2, SearchLimit = Scene.TerrainMatrix.GetUpperBound(0) * 2, //寻径限度(太小可能导致找不到路径) }; List<PathFinderNode> pathTemp = pathFinderFast.FindPath(new Point2D((int)Coordinate.X, (int)Coordinate.Y), new Point2D((int)end.X, (int)end.Y)); if (pathTemp != null && pathTemp.Count > 1) { path = pathTemp; path.Remove(path[path.Count - 1]); StraightRunTo(new Point(path[path.Count - 1].X, path[path.Count - 1].Y)); } } else { if (path != null) { path.Clear(); } StraightRunTo(end); } }
public override void ComputePossibleMoves(List <Move> possibleMoves, List <Position> includedPositions, MoveFilter moveFilter) { if ((moveFilter & MoveFilter.Move) == 0) { return; } if (Unit.Power == 0) { return; } // Never called by controls List <Tile> openList = new List <Tile>(); List <Tile> reachedTiles = new List <Tile>(); List <Position> reachedPos = new List <Position>(); Tile startTile = Unit.Game.Map.GetTile(Unit.Pos); openList.Add(startTile); reachedTiles.Add(startTile); while (openList.Count > 0) { Tile tile = openList[0]; openList.RemoveAt(0); // Distance at all double d = tile.Pos.GetDistanceTo(this.Unit.Pos); if (d >= Range) { continue; } foreach (Tile n in tile.Neighbors) { if (n.Pos == Unit.Pos) { continue; } if (includedPositions != null) { if (!includedPositions.Contains(n.Pos)) { continue; } } if (!reachedTiles.Contains(n)) { reachedTiles.Add(n); double d1 = n.Pos.GetDistanceTo(this.Unit.Pos); if (d1 < Range) { openList.Add(n); Move move = new Move(); move.MoveType = MoveType.Move; PathFinderFast pathFinder = new PathFinderFast(Unit.Owner.Game.Map); move.Positions = pathFinder.FindPath(Unit, Unit.Pos, n.Pos); if (move.Positions != null) { move.UnitId = Unit.UnitId; move.PlayerId = Unit.Owner.PlayerModel.Id; while (move.Positions.Count > Range + 1) { move.Positions.RemoveAt(move.Positions.Count - 1); } Position finalPos = move.Positions[move.Positions.Count - 1]; if (!reachedPos.Contains(finalPos)) { reachedPos.Add(finalPos); // Do not move on other units if (Unit.Game.Map.GetTile(finalPos).Unit == null) { possibleMoves.Add(move); } else { //int x = 0; } } } } } } } }