/// <summary> /// Verifies if the target has been reached by the current node. /// If affirmative, a flag is set, as well as the destination leaf. /// </summary> /// <param name="map">Scene map.</param> /// <param name="current">Current node in question.</param> /// <param name="target">Target's position.</param> private void checkFound(Map map, Node current, Map.Pos target) { if (current.pos == target) { foundTarget = true; end = current; } }
/// <summary> /// Returns if the given space is empty or not. /// </summary> private bool hasWall(Map.Pos space) { if (currentScene.map.getSpaceType(space) == Map.SpaceType.Wall) { return(true); } return(false); }
/*********************************************************************/ /* Class Methods */ /*********************************************************************/ /// <summary> /// Calculates and returns, if possible, best route for ghost to reach pacman. /// </summary> /// <param name="map">Map used in search algorithm.</param> /// <param name="pacpos">Pacman's position in map.</param> public bool calcPathToPac(Map map, Map.Pos pacpos) { pathToPac = pathfinder.findBestPath(map, this.pos, pacpos); if ((pathToPac != null) && (pathToPac.Count != 0)) { return(false); } return(true); }
private bool hasSomeone(Map.Pos pos) { if (currentScene.pacman.pos == pos) { return(true); } foreach (Ghost ghost in currentScene.ghosts) { if (ghost.pos == pos) { return(true); } } return(false); }
/// <summary> /// Finds and returns the best path to be followed from the origin postion, /// to the targets position, on the given map. /// Theoretically, I should only return the first position in the best path, /// since it is calculated on every change in the scene, but I prefered to leave /// it this way for now, in case I find a use for it later. /// </summary> /// <param name="map">Scene map.</param> /// <param name="origin">Origin's position.</param> /// <param name="target">Target's position.</param> public Stack <Pathfinder.Direction> findBestPath(Map map, Map.Pos origin, Map.Pos target) { // Setup visited map initVisitedMap(map); // reset pathfinders state reset(); // Setup root root.pos = origin; visitedMap[root.pos.x, root.pos.y] = true; // performs inital step step(map, root, target); // if target is not found in the frist step, enter step loop Node nextTry; while (!foundTarget) { nextTry = findLowerCost(); if (noSolution) { return(null); } visitedMap[nextTry.pos.x, nextTry.pos.y] = true; stepQue.Remove(nextTry); step(map, nextTry, target); } // fill direction stack fillBestPath(); return(bestPath); }
/// <summary> /// Returns a wall texture, taking in account its adjacent sapces. /// Look, I know im loading the same textures flipped 3 times, but /// honestly, each one is like 1K, f*****g 1K. I rather load 1K four /// times, and flip the images in Gimp, than implement a 100 line logic /// code that does is automatically. /// </summary> private Texture2D getWallTexture(SpriteBatch sb, Map.Pos pos) { Map.SpaceType a, b, c, d; a = currentScene.map.getSpaceType(pos - Map.unity); b = currentScene.map.getSpaceType(pos - Map.unitx); c = currentScene.map.getSpaceType(pos + Map.unitx); d = currentScene.map.getSpaceType(pos + Map.unity); if (a == Map.SpaceType.Empty) { if (b == Map.SpaceType.Empty) { if (c == Map.SpaceType.Empty) { if (d == Map.SpaceType.Empty) { return(wallDot); } else { return(wallSimpleUp); } } else { if (d == Map.SpaceType.Empty) { return(wallSimpleLeft); } else { return(wallLDown); } } } else { if (c == Map.SpaceType.Empty) { if (d == Map.SpaceType.Empty) { return(wallSimpleRight); } else { return(wallLLeft); } } else { if (d == Map.SpaceType.Empty) { return(wallLineHorizontal); } else { return(wallTDown); } } } } else { if (b == Map.SpaceType.Empty) { if (c == Map.SpaceType.Empty) { if (d == Map.SpaceType.Empty) { return(wallSimpleDown); } else { return(wallLineVertical); } } else { if (d == Map.SpaceType.Empty) { return(wallLRight); } else { return(wallTRight); } } } else { if (c == Map.SpaceType.Empty) { if (d == Map.SpaceType.Empty) { return(wallLUp); } else { return(wallTLeft); } } else { if (d == Map.SpaceType.Empty) { return(wallTUp); } else { return(wallCross); } } } } }
/// <summary> /// Performs a step, where every adjacent space to the current node is tested to see /// if it is a plausible candidate for a next direction to be followed in the /// pathfinding process. /// Is the node in a given direction is empty and has not been visited, it will /// be added to the the stepQue, as well as the main tree. /// If the target is reached in one of the directions adjacent to the current Node, /// the target is set as 'found'. /// </summary> /// <param name="map">Scene map.</param> /// <param name="current">Current node in question.</param> /// <param name="target">Target's position.</param> private void step(Map map, Node current, Map.Pos target) { // Test all adjacent nodes. // Left if ((map.getSpaceType(current.pos - Map.unitx) == Map.SpaceType.Empty) && (!visitedMap[current.pos.x - 1, current.pos.y])) { Node left = new Node(); left.pos.x = current.pos.x - 1; left.pos.y = current.pos.y; left.currentCost++; left.totalCost = left.currentCost + calcPathCost(left.pos, target); addTreeNode(current, left, Direction.Left); checkFound(map, left, target); if (!foundTarget) { addQueNode(left); } else { return; } } // Right if ((map.getSpaceType(current.pos + Map.unitx) == Map.SpaceType.Empty) && (!visitedMap[current.pos.x + 1, current.pos.y])) { Node right = new Node(); right.pos.x = current.pos.x + 1; right.pos.y = current.pos.y; right.currentCost++; right.totalCost = right.currentCost + calcPathCost(right.pos, target); addTreeNode(current, right, Direction.Right); checkFound(map, right, target); if (!foundTarget) { addQueNode(right); } else { return; } } // Up if ((map.getSpaceType(current.pos - Map.unity) == Map.SpaceType.Empty) && (!visitedMap[current.pos.x, current.pos.y - 1])) { Node up = new Node(); up.pos.x = current.pos.x; up.pos.y = current.pos.y - 1; up.currentCost++; up.totalCost = up.currentCost + calcPathCost(up.pos, target); addTreeNode(current, up, Direction.Up); checkFound(map, up, target); if (!foundTarget) { addQueNode(up); } else { return; } } // Down if ((map.getSpaceType(current.pos + Map.unity) == Map.SpaceType.Empty) && (!visitedMap[current.pos.x, current.pos.y + 1])) { Node down = new Node(); down.pos.x = current.pos.x; down.pos.y = current.pos.y + 1; down.currentCost++; down.totalCost = down.currentCost + calcPathCost(down.pos, target); addTreeNode(current, down, Direction.Down); checkFound(map, down, target); if (!foundTarget) { addQueNode(down); } else { return; } } }
/// <summary> /// Returns the Manhattan distance between two positions. /// </summary> /// <param name="origin">Origin position.</param> /// <param name="dest">Destination position.</param> private int calcPathCost(Map.Pos origin, Map.Pos dest) { return(Math.Abs(origin.x - dest.x) + Math.Abs(origin.y - dest.y)); }