public static TileSelector CircularSelector(Level level, Tile currentTile, int radius) { var selector = new TileSelector(); for (int i = -radius; i <= radius; i++) { for (int j = -radius; j <= radius; j++) { if (Math.Abs(i) + Math.Abs(j) <= radius) { Tile t = level.GetTileAt(currentTile.XCoord + j, currentTile.YCoord + i); if (t != null) selector.AddValidTile(t); } } } return selector; }
public static TileSelector StandardMovementTileSelector(Level level, Tile currentTile, ActorBase actor) { var selector = new TileSelector(); int movementRange = actor.CurrentStats.MovementRange; for (int i = -movementRange; i <= movementRange; i++) { for (int j = -movementRange; j <= movementRange; j++) { if (Math.Abs(i) + Math.Abs(j) <= movementRange) { Tile t = level.GetTileAt(currentTile.XCoord + j, currentTile.YCoord + i); if (t != null && t.ActorInTile == null) { if (AStar.CalculateAStarPath(currentTile, t, level, actor) != null) { selector.AddValidTile(t); } } } } } return selector; }
private static float CalculateMovementCost(ActorBase actor, Level level, int currentX, int currentY, int candidateX, int candidateY) { var currentTile = level.GetTileAt(currentX, currentY); var candidateTile = level.GetTileAt(candidateX, candidateY); return (float)Math.Abs(currentTile.GameHeight - candidateTile.GameHeight); }
private static IList<Tile> CalculatePath(Tile start, Tile goal, Level level, Node[,] nodes, ActorBase actor) { nodes[start.XCoord, start.YCoord].Cost = 0; nodes[start.XCoord, start.YCoord].Depth = 0; var open = new List<Node>(); var closed = new List<Node>(); var path = new List<Tile>(); int depth = 0; open.Add(nodes[start.XCoord, start.YCoord]); while (depth < MaximumSearchDistance && (open.Count != 0)) { Node current = open[0]; if (current == nodes[goal.XCoord, goal.YCoord]) { break; } open.RemoveAt(0); closed.Add(current); for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { if (x == 0 && y == 0) continue; if (x != 0 && y != 0) continue; int candidateX = x + current.X; int candidateY = y + current.Y; if (CanMoveToTile(actor, level, start.XCoord, start.YCoord, current.X, current.Y, candidateX, candidateY)) { float nextStepCost = current.Cost + CalculateMovementCost(actor, level, current.X, current.Y, candidateX, candidateY); Node neighbor = nodes[candidateX, candidateY]; if (nextStepCost < neighbor.Cost) { if (open.Contains(neighbor)) { open.Remove(neighbor); } if (closed.Contains(neighbor)) { closed.Remove(neighbor); } } if (!open.Contains(neighbor) && !closed.Contains(neighbor)) { neighbor.Cost = nextStepCost; neighbor.Heuristic = GetHeuristicCost(actor, level.GetTileAt(candidateX, candidateY), goal); depth = Math.Max(depth, neighbor.SetParent(current)); open.Add(neighbor); open = open.OrderBy(o => o.TotalCost()).ToList(); } } } } } if (nodes[goal.XCoord, goal.YCoord].Parent == null) return null; Node target = nodes[goal.XCoord, goal.YCoord]; while (target != nodes[start.XCoord, start.YCoord]) { path.Insert(0, level.GetTileAt(target.X, target.Y)); target = target.Parent; } path.Insert(0, start); if (path.Count > actor.CurrentStats.MovementRange + 1) return null; return path; }
private static bool CanMoveToTile(ActorBase actor, Level level, int startX, int startY, int currentX, int currentY, int candidateX, int candidateY) { if (candidateX < 0 || candidateY < 0 || candidateX >= level.Length || candidateY >= level.Width || (candidateX == startX && candidateY == startY)) { return false; } var currentTile = level.GetTileAt(currentX, currentY); var candidateTile = level.GetTileAt(candidateX, candidateY); if (Math.Abs(currentTile.GameHeight - candidateTile.GameHeight) > actor.CurrentStats.MaximumHeightCanMove) return false; if (candidateTile.ActorInTile != null && candidateTile.ActorInTile.Team != actor.Team) return false; return true; }