With the tile collision and tile artwork laid out, now I only need the enemy objects to follow them. Currently, they are just following a straight line from their current position to the target position, with no regard for any "Walls".
Principles of Pathfinding
The A-Star Search is the backbone of pathfinding. There are many resources online that describe it in better detail, but I'll summarize it here for my own learning. It is used for finding the optimal path between two coordinates based on the weighted movement options. Based on the tile setup in previous posts, the screen can be summarized as a weighted grid of nodes.
The movement between each nodes is a directional vector (ex: moving one node right is a [1, 0] vector). The cost of each movement is weighted, either based on distance (an orthogonal movement is weighted as 1, while diagonal is weighted as 1.41) or special conditions (slowing effects on certain nodes increase cost value). From the start position, the cost value of each neighboring node is assessed. A heuristic calculation is performed to sum the movement's cost and the remaining required distance for each node. The neighboring node with the lowest heuristic value is considered the best move. The neighboring nodes from that position are then calculated. This reiterates until the goal node has been reached.
Apparently, this algorithm was published in 1968 for use in graph traversal. I'm not certain where that is used; perhaps it's something like Google maps, which generates multiple paths to a destination based on distance, traffic, and cost, but I'm certain if they didn't think it'd be used for programming AI for fun little games.
The Pseudo-Code
- Convert the "Start" and "End" coordinates to tile vectors
- Input "Grid", "Start", and "End" values into A-Star Search function
- A-Star Search function:
- Create a "PriorityQueue" object with heap functions
- Heaps are data structures similar to lists, but always sort items based on value (smallest to largest). This will be used to determining the shortest route between two nodes, based on the weighted "Cost" value of movement.
- Inputs the "Start" node into the "PriorityQueue"
- Create empty "Path" and "Cost" dictionaries
- Create "Check" node equal to "Start" to start iterating through nodes
- For each neighboring node ("Neighbor"), determine if:
- "Neighbor" is available (not in "Walls" list)
- If so, check if "Neighbor" has already been added to the "Cost" list, or
- if so, check if the "Cost" value is less than existing value
- If "Neighbor" passes the check:
- Assign cost value to the "Neighbor" key in the "Cost" dictionary
- Calculate "Heuristic" value from the sum of:
- Cost value of movement to "Neighbor"
- Remaining distance from "Neighbor" to "End"
- Set "Heuristic" value to the "Neighbor" key in the "PriorityQueue"
- Calculate directional vector from "Start" to the "Neighbor"
- Assign the directional vector to the "Neighbor" key in the "Path" dictionary
- Update the "Check" value to the lowest "Heuristic" value in the "PriorityQueue"
- This decides which node is the optimal choice for efficient
- Additional neighboring nodes are assessed per Steps 5-6 from the updated "Check"
- Reiterate until "Check" equals "End"
- The A-Star Search returns a dictionary of vectors, with node keys
- See below for the visuals of the A-Star search.
- Create vector list from A-Star "Path" dictionary:
- Create "Temp" node equal to "Start"
- Create empty "Directions" list
- Input "Temp" as key to "Path" dictionary to get vector
- Add vector to "Directions" list
- Update the "Temp" node with vector
- Reiterate until "Temp" equals "End"
Comments
Post a Comment