public static bool CanWalkToSquare(Unit unit, PathSquare pathSquare, bool checkUnitCollision = false) { var sqr = pathSquare.square; if (sqr.obstacles.Count == 0) { return(sqr.isWalkable); } else { if (checkUnitCollision) { foreach (var obj in sqr.obstacles.Values) { if (obj != unit) { //Debug.Log(obj.name); return(false); } } } } return(true); }
public PathSquareNeighbourInfo(PathSquare neighbour, double dist, PathSquare[] check) { this.neighbour = neighbour; this.distance = dist; this.diagonalCheck = check; this.isDiagonal = true; }
public static PathInfo GetStraightPath(Unit unit, PathSquare start, PathSquare end) { HashSet <PathSquare> closedSet = new HashSet <PathSquare>(); ResetPathSquare(); bool reachedGoal = false; var direction = (end.pos.ToVector() - start.pos.ToVector()).normalized; var current = start; while (current != null) { if (current == end) { //return PathInfo.GenerateWaypoints(start, current); reachedGoal = true; } closedSet.Add(current); var next = current.pos.ToVector() + direction; PathSquareNeighbourInfo nextNeighbour; if (current.neighbours.TryGetValue(next.ConvertToIPosition(), out nextNeighbour)) { if (!closedSet.Contains(nextNeighbour.neighbour)) { if (nextNeighbour.neighbour == end || CanWalkToSquare(unit, nextNeighbour)) { nextNeighbour.neighbour.parent = current; current = nextNeighbour.neighbour; continue; } } } break; } if (reachedGoal) { return(PathInfo.GenerateWaypoints(start, current)); } return(null); }
public static PathInfo GenerateWaypoints(PathSquare start, PathSquare end) { var newPath = new PathInfo(start.pos, end.pos); var current = end; var lastSqr = end; Vector3 dir = Vector3.zero; while (current != null) { /*if(lastSqr != end) * { * var lastVec = lastSqr.pos.ToVector(); * var curVec = current.pos.ToVector(); * * var tDir = (curVec - lastVec).normalized; * * Debug.Log(tDir); * * if(tDir != dir) * { * newPath.waypoints.Add(current.pos); * dir = tDir; * } * } * else * { * newPath.waypoints.Add(current.pos); * }*/ newPath.points.Add(current.pos); lastSqr = current; current = current.parent; } newPath.points.Reverse(); newPath.waypoints.Reverse(); return(newPath); }
public static PathInfo GetPath(Unit unit, Vector3 start, Vector3 end, PathType type = PathType.Shortest) { PathSquare startSqr = GetPathSquare(start); PathSquare endSqr = GetPathSquare(end); //Debug.Log(end.x); if (startSqr != null && endSqr != null) { switch (type) { case PathType.Shortest: return(GetShortestPath(unit, startSqr, endSqr)); case PathType.Straight: return(GetStraightPath(unit, startSqr, endSqr)); default: return(null); } } return(null); }
public bool Equals(PathSquare obj) { return(obj.square.position == this.square.position); }
public double Distance(PathSquare sqr) { return(sqr.square.position.Distance(this.square.position)); }
/// <summary> /// Update my "map" of all permanent objects (rocks and destroyed tanks) and empty GridSquares I have seen so far. /// </summary> private void UpdateMyMap() { int x, y; // initialise mygrid if it hasn't yet been created if (MyMap == null) { MyMap = new PathSquare[MyWorldState.GridWidthInSquares, MyWorldState.GridHeightInSquares]; for (x = 0; x < MyWorldState.GridWidthInSquares; x++) { for (y = 0; y < MyWorldState.GridHeightInSquares; y++) { MyMap[x, y] = new PathSquare(x, y); // set each unseen grid square to null } } } // remove previous tank location from MyMap foreach (var square in MyMap) { if ( square.GridSq.Contents == GridSquare.ContentType.TankUp || square.GridSq.Contents == GridSquare.ContentType.TankRight || square.GridSq.Contents == GridSquare.ContentType.TankLeft || square.GridSq.Contents == GridSquare.ContentType.TankDown ) { if (square.GridSq.Player != MyWorldState.ID) { square.HasBeenSeen = false; } square.GridSq = new GridSquare(square.X, square.Y, GridSquare.ContentType.Empty); square.IsBlocked = false; } } // update the map in mygrid foreach (GridSquare gs in MyWorldState.MyVisibleSquares) { if (MyMap[gs.X, gs.Y].HasBeenSeen == false) // not yet seen GridSquare gs { MyMap[gs.X, gs.Y].HasBeenSeen = true; // record fixed objects - rocks, destroyed tanks and empty squares if (gs.Contents == GridSquare.ContentType.Rock) { MyMap[gs.X, gs.Y].GridSq = new GridSquare(gs.X, gs.Y, GridSquare.ContentType.Rock); MyMap[gs.X, gs.Y].IsBlocked = true; } else if (gs.Contents == GridSquare.ContentType.DestroyedTank) { MyMap[gs.X, gs.Y].GridSq = new GridSquare(gs.X, gs.Y, GridSquare.ContentType.DestroyedTank); MyMap[gs.X, gs.Y].IsBlocked = true; } else if (gs.Contents == GridSquare.ContentType.Empty) { MyMap[gs.X, gs.Y].GridSq = new GridSquare(gs.X, gs.Y, GridSquare.ContentType.Empty); } // record moving objects - tanks else if (gs.Contents == GridSquare.ContentType.TankDown) { MyMap[gs.X, gs.Y].GridSq = new GridSquare(gs.X, gs.Y, GridSquare.ContentType.TankDown, gs.Player); MyMap[gs.X, gs.Y].IsBlocked = true; } else if (gs.Contents == GridSquare.ContentType.TankLeft) { MyMap[gs.X, gs.Y].GridSq = new GridSquare(gs.X, gs.Y, GridSquare.ContentType.TankLeft, gs.Player); MyMap[gs.X, gs.Y].IsBlocked = true; } else if (gs.Contents == GridSquare.ContentType.TankRight) { MyMap[gs.X, gs.Y].GridSq = new GridSquare(gs.X, gs.Y, GridSquare.ContentType.TankRight, gs.Player); MyMap[gs.X, gs.Y].IsBlocked = true; } else if (gs.Contents == GridSquare.ContentType.TankUp) { MyMap[gs.X, gs.Y].GridSq = new GridSquare(gs.X, gs.Y, GridSquare.ContentType.TankUp, gs.Player); MyMap[gs.X, gs.Y].IsBlocked = true; } } else if (gs.Contents == GridSquare.ContentType.DestroyedTank && MyMap[gs.X, gs.Y].GridSq.Contents != GridSquare.ContentType.DestroyedTank) { MyMap[gs.X, gs.Y].GridSq = new GridSquare(gs.X, gs.Y, GridSquare.ContentType.DestroyedTank); // record new destroyed tanks even if seen before. MyMap[gs.X, gs.Y].IsBlocked = true; } else if (gs.Contents == GridSquare.ContentType.TankDown) { MyMap[gs.X, gs.Y].GridSq = new GridSquare(gs.X, gs.Y, GridSquare.ContentType.TankDown, gs.Player); MyMap[gs.X, gs.Y].IsBlocked = true; } else if (gs.Contents == GridSquare.ContentType.TankLeft) { MyMap[gs.X, gs.Y].GridSq = new GridSquare(gs.X, gs.Y, GridSquare.ContentType.TankLeft, gs.Player); MyMap[gs.X, gs.Y].IsBlocked = true; } else if (gs.Contents == GridSquare.ContentType.TankRight) { MyMap[gs.X, gs.Y].GridSq = new GridSquare(gs.X, gs.Y, GridSquare.ContentType.TankRight, gs.Player); MyMap[gs.X, gs.Y].IsBlocked = true; } else if (gs.Contents == GridSquare.ContentType.TankUp) { MyMap[gs.X, gs.Y].GridSq = new GridSquare(gs.X, gs.Y, GridSquare.ContentType.TankUp, gs.Player); MyMap[gs.X, gs.Y].IsBlocked = true; } } }
public static PathInfo GetShortestPath(Unit unit, PathSquare start, PathSquare end) { HashSet <PathSquare> closedSet = new HashSet <PathSquare>(); HashSet <PathSquare> openSet = new HashSet <PathSquare>(); PathSquare closestSquare = null; double closestDistance = 9999; openSet.Add(start); ResetPathSquare(); start.gScore = 0; start.fScore = start.Distance(end); double bestRouteDist = start.Distance(end); while (openSet.Count > 0) { var current = openSet.OrderBy(n => n.fScore).FirstOrDefault(); if (current == end) { return(PathInfo.GenerateWaypoints(start, current)); } openSet.Remove(current); closedSet.Add(current); foreach (var pair in current.neighbours) { var neighbourInfo = pair.Value; var neighbour = neighbourInfo.neighbour; var distance = neighbourInfo.distance; if (closedSet.Contains(neighbour)) { continue; } if (!CanWalkToSquare(unit, neighbourInfo)) { continue; } var alternativeDistance = current.gScore + distance; /*if(alternativeDistance > bestRouteDist * 2) * { * continue; //stop searching for route that's longer than 2x the optimal path * }*/ if (!openSet.Contains(neighbour)) { openSet.Add(neighbour); } else if (alternativeDistance >= neighbour.gScore) { continue; } var estimatedDistance = neighbour.Distance(end); neighbour.parent = current; neighbour.gScore = alternativeDistance; neighbour.fScore = alternativeDistance + estimatedDistance; if (closestDistance > estimatedDistance) { closestSquare = neighbour; closestDistance = estimatedDistance; } } } if (closestSquare == null) { return(null); } if (closestSquare.Distance(end) < start.Distance(end)) { var path = PathInfo.GenerateWaypoints(start, closestSquare); path.reachable = false; return(path); } else { return(null); } }
public static void InitPathSquares(Level level) { pathSquares = new Dictionary <IPosition, PathSquare>(); List <IPosition> neighbourPositions = new List <IPosition>() { new IPosition(-1, 0, 0), //4, left new IPosition(1, 0, 0), //6, right new IPosition(0, 0, -1), //8, up new IPosition(0, 0, 1), //2, down }; Dictionary <IPosition, IPosition[]> neighbourDiagonalPositions = new Dictionary <IPosition, IPosition[]>() { { new IPosition(-1, 0, 1), new IPosition[2] { new IPosition(-1, 0, 0), //4, left new IPosition(0, 0, 1), //2, down } }, //1 { new IPosition(-1, 0, -1), new IPosition[2] { new IPosition(-1, 0, 0), //4, left new IPosition(0, 0, -1), //8, up } }, //7 { new IPosition(1, 0, -1), new IPosition[2] { new IPosition(0, 0, -1), //8, up new IPosition(1, 0, 0), //6, right } }, //9 { new IPosition(1, 0, 1), new IPosition[2] { new IPosition(1, 0, 0), //6, right new IPosition(0, 0, 1), //2, down } }, //3 }; foreach (var sqr in level.map.Values) { var newPathSqr = new PathSquare(sqr); pathSquares.Add(sqr.position, newPathSqr); sqr.CheckWalkable(); } foreach (var pathSqr in pathSquares.Values) { var sqrPosition = pathSqr.pos; foreach (var dir in neighbourPositions) { var pos = sqrPosition + dir; PathSquare square; if (pathSquares.TryGetValue(pos, out square)) { pathSqr.neighbours.Add(square.pos, new PathSquareNeighbourInfo(square, square.Distance(pathSqr))); } } foreach (var diagonal in neighbourDiagonalPositions) { var pos = sqrPosition + diagonal.Key; PathSquare square; if (pathSquares.TryGetValue(pos, out square)) { var diagPos1 = sqrPosition + diagonal.Value[0]; var diagPos2 = sqrPosition + diagonal.Value[1]; PathSquare sqr1; PathSquare sqr2; if (pathSquares.TryGetValue(diagPos1, out sqr1) && pathSquares.TryGetValue(diagPos2, out sqr2)) { pathSqr.neighbours.Add(square.pos, new PathSquareNeighbourInfo(square, square.Distance(pathSqr), new PathSquare[] { sqr1, sqr2 })); } } } } }
public PathSquareNeighbourInfo(PathSquare neighbour, double dist) { this.neighbour = neighbour; this.isDiagonal = false; this.distance = dist; }