1

I am doing my first attempt at introducing pathfinding in one of my games. So far I have implemented an A* algorithm which seems to correctly find a path around a wall that I set up to the location specified according to print statements. However, from the way I understand it, the method I use to generate the path returns a path from the goal to the character rather than the other way around. Therefore I need to reverse the path in order for my character to move to the specified location (if I understood things correctly). How do I do this in the best way possible?

Pathfinder code:

public class PathFinder
{
    public static Map<Location, Location> createPath(Location start, Location goal)
    {
        //A "Location" is a simple vector object that accepts an X and Y value.
        HashMap<Location, Location> locationParents = new HashMap<>();
        HashMap<Location, Integer> movementCosts = new HashMap<>();

        PriorityQueue frontier = new PriorityQueue();
        frontier.push(start, 0);

        locationParents.put(start, null);
        movementCosts.put(start, 0);

        //"While we have locations that we need to check in order to get a path"
        while(!frontier.isEmpty())
        {
            Location current = frontier.pop();

            //Break if we found the goal
            if(current.equals(goal))
                break;

            //Neighbours around a location are locations in all 8 directions next to it that are passable
            for(Location next : SquareGrid.getLocationNeighbours(current))
            {
                int newCost = movementCosts.get(current) + SquareGrid.getLocationCost(next);
                if(!movementCosts.containsKey(next) || newCost < movementCosts.get(next))
                {
                    movementCosts.put(next, newCost);
                    int priority = newCost + makeGuess(next, goal);
                    frontier.push(next, priority);
                    locationParents.put(next, current);
                }
            }
        }

        return locationParents;
    }

    private static int makeGuess(Location a, Location b)
    {
        return Math.abs(a.getX() - b.getX()) + Math.abs(a.getY() - b.getY());
    }

    private static class PriorityQueue
    {
        private LinkedList<LocationPair> elements = new LinkedList<>();

        public boolean isEmpty()
        {
            return elements.isEmpty();
        }

        public void push(Location loc, int cost)
        {
            elements.push(new LocationPair(loc, cost));
        }

        public Location pop()
        {
            int bestIndex = 0;

            for(int i = 0; i < elements.size(); i++)
            {
                if(elements.get(i).cost < elements.get(bestIndex).cost)
                    bestIndex = i;
            }

            return elements.remove(bestIndex).location;
        }

        private static class LocationPair
        {
            private final Location location;
            private final int cost;

            private LocationPair(Location location, int cost)
            {
                this.location = location;
                this.cost = cost;
            }
        }
    }
}

I want the movement code inside the character class to be something like this:

            Location currentPos = new Location(x, y);
            //Next position to move to
            Location nextPosition = targets.get(currentPos);

            xVel = Integer.compare(parentPos.getX(), currentPos.getX());
            yVel = Integer.compare(parentPos.getY(), currentPos.getY());

            x += xVel;
            y += yVel;

Since this is my first time doing pathfinding for a game I might be approaching this incorrectly though I am not sure.

  • Well, the right way to do it is to find a path from the character to the goal, so likely you have a bug that should be fixed. – markspace Oct 26 '19 at 15:46
  • You are passing start and goal location, where is your location list in which you want to find the goal path? You are adding your start location in a queue so queue will have only one start location so why while loop? – Aqeel Haider Oct 26 '19 at 15:51
  • Java has a priority queue, there's no need to invent your own: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/PriorityQueue.html – markspace Oct 26 '19 at 15:55
  • @AqeelHaider My method returns locationParents, and is the map that I'd like to use to tell my character where to move. – That Martin Guy Oct 26 '19 at 17:46
  • @markspace My priority queue has its own behaviour that is not covered by the one that comes with Java. – That Martin Guy Oct 26 '19 at 17:46
  • If your pathfinding is giving you a path from the goal to the source, then when you find the path just reverse your start and goal locations and the path returned should be in the order that you need. – Durstann Feb 07 '21 at 06:26

0 Answers0