// Finds selectable tiles and updates currentTile as current, occupied public void FindSelectableTiles(Tile startTile, float movementRange) { // if selectable tiles were not removed do not recompute. if (selectableTiles.Count > 0) { foreach (Tile tile in selectableTiles) { tile.selectable = true; } return; } // init Dijkstra PriorityQueue <TileDistancePair> processing = new PriorityQueue <TileDistancePair>(); // Compute Adjacency List and reset all distances. InitPathFinding(startTile); startTile.selectable = true; selectableTiles.Add(startTile); processing.Enqueue(new TileDistancePair(0, startTile)); // relax edges with minimum SP estimate while (processing.Count() > 0) { TileDistancePair temp = processing.Dequeue(); float distanceEstimate = temp.d; Tile node = temp.t; if ((int)Math.Round(distanceEstimate) == node.distance) { foreach (Tile neighbour in node.adjacencyList) { int newEstimate = node.distance + neighbour.movementCost; if (neighbour.walkable && neighbour.distance > newEstimate && newEstimate <= movementRange) { if (!neighbour.occupied) { neighbour.selectable = true; selectableTiles.Add(neighbour); } else { UnitsInSelectableRange.Add(neighbour); } neighbour.distance = newEstimate; neighbour.parent = node; processing.Enqueue(new TileDistancePair(newEstimate, neighbour)); } } } } }
// selectable means that only selectable tiles will be added (for walking within the selectable tile zone) // playerTargeting means that the only occupied tile allowed will be the goal tile (to allow targeting of units) public static void GeneratePath(Map map, Tile start, Tile goal, bool selectable = false, bool playerTargeting = false) { var frontier = new PriorityQueue <TileDistancePair>(); map.InitPathFinding(start); start.parent = null; frontier.Enqueue(new TileDistancePair(0, start)); while (frontier.Count() > 0) { TileDistancePair temp = frontier.Dequeue(); Tile current = temp.t; if (current.Equals(goal)) { break; } foreach (Tile neighbour in current.adjacencyList) { int newEstimate = current.distance + neighbour.movementCost; if (neighbour.walkable && neighbour.distance > newEstimate) // && (!neighbour.occupied || (playerTargeting && neighbour == goal)) ) { // check if neighbour is selectable, if 'selectable' setting is activated if (selectable && !neighbour.selectable && !map.UnitsInSelectableRange.Contains(neighbour)) { continue; } neighbour.distance = newEstimate; neighbour.parent = current; float priority = newEstimate + Heuristic(neighbour, goal); frontier.Enqueue(new TileDistancePair(priority, neighbour)); } } } }
// Need to write for all the targeting styles public bool PlayerTargetInAttackRange(Tile startTile, float attackRange, Unit player) { /*int[] hor = { -1, 0, 1, 0 }; * int[] vert = { 0, 1, 0, -1 }; * * int currX = startTile.gridPosition.x, currY = startTile.gridPosition.y; * * bool[] passable = new bool[4]; * * for (int i = 0; i < 4; i++) * { * passable[i] = true; * } * * for (int i = 1; i <= attackRange; i++) * { * for (int j = 0; j < 4; j++) * { * int newX = currX + i * hor[j]; * int newY = currY + i * vert[j]; * * if (newX >= 0 && newX < mapSize.x && newY >= 0 && newY < mapSize.y) * { * Tile newTile = tileList[newX][newY]; * if (newTile.walkable && passable[j]) * { * if (newTile == player.currentTile) * { * return true; * } * } * else * { * passable[j] = false; * } * } * } * }*/ PriorityQueue <TileDistancePair> processing = new PriorityQueue <TileDistancePair>(); // Compute Adjacency List and reset all distances. InitPathFinding(startTile); attackableTiles.Add(startTile); processing.Enqueue(new TileDistancePair(0, startTile)); // relax edges with minimum SP estimate while (processing.Count() > 0) { TileDistancePair temp = processing.Dequeue(); float distanceEstimate = temp.d; Tile node = temp.t; if ((int)Math.Round(distanceEstimate) == node.distance) { foreach (Tile neighbour in node.adjacencyList) { int newEstimate = node.distance + 1; if (neighbour.walkable && neighbour.distance > newEstimate && newEstimate <= attackRange) { if (neighbour == player.currentTile) { return(true); } neighbour.attackable = true; attackableTiles.Add(neighbour); neighbour.distance = newEstimate; processing.Enqueue(new TileDistancePair(newEstimate, neighbour)); } } } } return(false); }
public void FindAttackableTiles(Tile startTile, float attackRange, TargetingStyle targetingStyle = TargetingStyle.SINGLE) { #region Basic Targeting (Deprecated) /*if (targetingStyle == TargetingStyle.SINGLE || targetingStyle == TargetingStyle.MULTI || targetingStyle == TargetingStyle.SELFSINGLE) * { * int[] hor = { -1, 0, 1, 0 }; * int[] vert = { 0, 1, 0, -1 }; * * int currX = startTile.gridPosition.x, currY = startTile.gridPosition.y; * * bool[] passable = new bool[4]; * for (int i = 0; i < 4; i++) * { * passable[i] = true; * } * * for (int i = 1; i <= attackRange; i++) * { * for (int j = 0; j < 4; j++) * { * int newX = currX + i * hor[j]; * int newY = currY + i * vert[j]; * * if (newX >= 0 && newX < mapSize.x && newY >= 0 && newY < mapSize.y) * { * if (tileList[newX][newY].walkable && passable[j]) * { * tileList[newX][newY].attackable = true; * attackableTiles.Add(tileList[newX][newY]); * } * else * { * passable[j] = false; * } * } * } * } * }*/ #endregion #region Basic Targeting if (targetingStyle == TargetingStyle.SINGLE || targetingStyle == TargetingStyle.MULTI || targetingStyle == TargetingStyle.SELFSINGLE) { PriorityQueue <TileDistancePair> processing = new PriorityQueue <TileDistancePair>(); // Compute Adjacency List and reset all distances. InitPathFinding(startTile); attackableTiles.Add(startTile); processing.Enqueue(new TileDistancePair(0, startTile)); // relax edges with minimum SP estimate while (processing.Count() > 0) { TileDistancePair temp = processing.Dequeue(); float distanceEstimate = temp.d; Tile node = temp.t; if ((int)Math.Round(distanceEstimate) == node.distance) { foreach (Tile neighbour in node.adjacencyList) { int newEstimate = node.distance + 1; if (neighbour.walkable && neighbour.distance > newEstimate && newEstimate <= attackRange) { neighbour.attackable = true; attackableTiles.Add(neighbour); neighbour.distance = newEstimate; processing.Enqueue(new TileDistancePair(newEstimate, neighbour)); } } } } } #endregion #region Self Targeting if (targetingStyle == TargetingStyle.SELF || targetingStyle == TargetingStyle.SELFSINGLE) { startTile.attackable = true; attackableTiles.Add(startTile); } #endregion #region Radius Targeting if (targetingStyle == TargetingStyle.RADIUS) { // init Dijkstra PriorityQueue <TileDistancePair> processing = new PriorityQueue <TileDistancePair>(); // Compute Adjacency List and reset all distances. InitPathFinding(startTile, true); attackableTiles.Add(startTile); processing.Enqueue(new TileDistancePair(0, startTile)); // relax edges with minimum SP estimate while (processing.Count() > 0) { TileDistancePair temp = processing.Dequeue(); float distanceEstimate = temp.d; Tile node = temp.t; if ((int)Math.Round(distanceEstimate) == node.distance) { foreach (Tile neighbour in node.adjacencyList) { int newEstimate = node.distance + 1; if (neighbour.walkable && neighbour.distance > newEstimate && newEstimate <= attackRange) { neighbour.attackable = true; attackableTiles.Add(neighbour); neighbour.distance = newEstimate; processing.Enqueue(new TileDistancePair(newEstimate, neighbour)); } } } } } #endregion #region Obstacle Targeting if (targetingStyle == TargetingStyle.OBSTACLES) { int[] hor = { -1, 0, 1, 0 }; int[] vert = { 0, 1, 0, -1 }; int currX = startTile.gridPosition.x, currY = startTile.gridPosition.y; bool[] passable = new bool[4]; for (int i = 0; i < 4; i++) { passable[i] = true; } for (int i = 1; i <= attackRange; i++) { for (int j = 0; j < 4; j++) { int newX = currX + i * hor[j]; int newY = currY + i * vert[j]; if (newX >= 0 && newX < mapSize.x && newY >= 0 && newY < mapSize.y) { if (!tileList[newX][newY].walkable) { tileList[newX][newY].attackable = true; attackableTiles.Add(tileList[newX][newY]); } else { passable[j] = false; } } } } } #endregion }