If you have played MMOARPG games, such as World of Warcraft, you will find that the walking of characters is very interesting. In order to simulate the real experience of walking, they will choose the shortest route to reach the destination, avoiding mountains or lakes, and bypassing boxes or woods until they reach the destination you selected. This seemingly ordinary pathfinding requires a certain pathfinding algorithm to solve when implemented in a program. How to find the shortest route in the shortest time is the first problem that the pathfinding algorithm must consider. In this article, we will explain step by step how pathfinding algorithms have evolved. You will see the problems encountered by an algorithm from simple to efficient, as well as the process of improvement. Read with questions in mind to understand faster. This article mainly contains the following contents:
1. How do characters in the game find their way?The way you see people walking: How developers actually see it: Or this: For a map, developers need to convert it into data objects through certain schemes. The most common one is to cut the map into grids. Of course, the map division method does not necessarily have to be grids. Polygons can also be used. This depends on your game. Generally, maps of the same area use fewer vertices, and the pathfinding algorithm will be faster. The commonly used data structure in pathfinding is the graph. Let's take a look at it below. 2. PictureBefore we talk about the pathfinding algorithm, let's first understand a data structure - graph. Data structure is the basis for our algorithm calculation. A good data structure not only makes it easier for us to understand the algorithm, but also improves the efficiency of the algorithm. In a sense, the grid is also an evolution of the graph, but the graphics have changed. Understanding the concept of graph can help us better understand the pathfinding algorithm. Basic definition of a graph:
3. Search Algorithm
Depth-First SearchThe depth-first algorithm has little to do with the minimum path, so we will only briefly introduce it.
Breadth-First SearchThe breadth-first search algorithm (BFS for short), also known as width-first search, is a graph search algorithm that is very suitable for exploring the first model of the shortest path. We will continue to talk about it along this line of thought. BFS is a blind search method that aims to systematically expand and check all nodes in the graph to find the result. In other words, it does not consider the possible address of the result and thoroughly searches the entire graph until the result is found. Its steps are as follows:
Grid: Let's look at the code (js): var frontier = new Array(); frontier.put(start); var visited = new Array(); visited[start] = true; while(frontier.length>0){ current = frontier.get(); //Find surrounding vertices for(next in graph.neighbors(current)){ var notInVisited = visited.indexOf(next)==-1; //Not visited if(notInVisited) { frontier.put(next); visited[next] = true; } } } From the above, we can see that the breadth search starts from the starting vertex, visits its child nodes (in the grid, visits the surrounding nodes), and then continuously loops this process until the target is found. This algorithm is more in line with conventional logic and enumerates all vertices. However, this method also has obvious disadvantages. defect:
How to solve this problem? Let's look at Dijkstra's algorithm. 4. Dijkstra algorithmThe breadth-first search algorithm solves the path planning problem from the starting vertex to the target vertex, but it is not the best and most suitable one because its edges have no weights (such as distance) and the path cannot be estimated to compare the best solution. Why is the weight so important? In the real environment, the route between two vertices is not always a straight line. It is necessary to bypass obstacles to reach the destination, such as forests, lakes, and mountains, which all need to be bypassed instead of directly passing through. For example, if I use the breadth-first algorithm, in the following situation, it will directly pass through the obstacle (green part), which is obviously not the result we want: Solve pain points:
The Dijkstra algorithm is an improvement based on the breadth-first algorithm. It adds the shortest edge to the shortest path tree and uses the greedy algorithm to calculate and eventually produce the best result. The specific steps are as follows:
Let’s look at the following example: Let's look at the code (js): var frontier = new PriorityQueue(); frontier.put(start); path = new Array(); //Each vertex path consumes cost_so_far = new Array(); path[start] = 0; cost_so_far[start] = 0 while(frontier.length>0){ current = frontier.get(); if current == goal: break //Find surrounding nodes for(next in graph.neighbors(current)){ var notInVisited = visited.indexOf(next)==-1; var new_cost = cost_so_far[current] + graph.cost(current, next); //Not visited or the path is closer if(notInVisited || new_cost < cost_so_far[next]) { cost_so_far[next] = new_cost; priority = new_cost; frontier.put(next, priority); path[next] = current; } } } We can see that although the Dijkstra algorithm is smarter than the breadth-first search and can avoid long routes or inaccessible areas based on cost_so_far, it still has a tendency to search blindly. A common situation in maps is to find the path between the target and the starting point, which has a certain directionality. As can be seen from the above figure, the Dijkstra algorithm also diffuses from the starting point to the child nodes in all directions. shortcoming:
How to solve the problem of not blindly searching the whole disk? Let's look at the Greedy Best First Search algorithm. 5. Greedy *** First SearchIn Dijkstra's algorithm, I have found its ultimate flaw, the search is blind. Here, we only use greedy first-order search to solve this pain point. How to solve it? We just need to change our concept slightly. In Dijkstra's algorithm, the priority queue uses the estimated value of each vertex to the starting vertex to sort. In the greedy first-order search, Solve pain points:
Which one is faster? Let's look at the following picture (breadth-first on the left, greedy-first on the right): From the above figure, we can clearly see that the algorithm on the right (greedy first-priority search) is faster than the one on the left. Although its path is not the longest and shortest, it is fast enough when there are the least obstacles. This is the advantage of the greedy algorithm, which searches based on the goal rather than a complete search. Let's look at the algorithm (js): frontier = new PriorityQueue(); frontier.put(start, 0) came_from = new Array(); came_from[start] = 0; while(frontier.length>0){ current = frontier.get() if current == goal: break for(next in graph.neighbors(current)){ var notInVisited = visited.indexOf(next)==-1; //Not visited if(notInVisited ) { //The closer the distance to the goal, the higher the priority priority = heuristic(goal, next); frontier.put(next, priority); came_from[next] = current; } } } function heuristic(a, b){ //Distance from the target return abs(ax - bx) + abs(ay - by) } shortcoming:
How to search for as few vertices as possible while ensuring the shortest path? Let's look at the A* algorithm. 6. A* AlgorithmFrom the evolution of the above algorithms, we gradually found two solutions for the shortest path and the least number of search vertices, Dijkstra algorithm and greedy *** first search. So is it possible for us to take advantage of the two algorithms and make the path search algorithm fast and efficient? The answer is yes. The A* algorithm does just that. It draws on the cost_so_far in the Dijkstra algorithm, sets weights for each edge length, and continuously calculates the distance from each vertex to the starting vertex to obtain the shortest route. It also draws on the advantage of the greedy first-order search algorithm of continuously moving toward the goal, and continuously calculates the distance from each vertex to the target vertex to guide the search queue to continuously approach the goal, thereby searching fewer vertices and maintaining efficient pathfinding. Solve pain points:
Let's look at the algorithm (js): var frontier = new PriorityQueue(); frontier.put(start); path = new Array(); cost_so_far = new Array(); path[start] = 0; cost_so_far[start] = 0 while(frontier.length>0){ current = frontier.get() if current == goal: break for(next in graph.neighbors(current)){ var notInVisited = visited.indexOf(next)==-1; var new_cost = cost_so_far[current] + graph.cost(current, next); //Not visited and the path is closer if(notInVisited || new_cost < cost_so_far[next]) { cost_so_far[next] = new_cost //Queue priority = new_cost (distance from vertex to starting vertex) + heuristic (distance from vertex to target vertex) priority = new_cost + heuristic(goal, next) frontier.put(next, priority) path[next] = current } } } function heuristic(a, b){ //Distance from the target return abs(ax - bx) + abs(ay - by) } The following are the pathfinding radar diagrams of the Dijkstra algorithm, the greedy algorithm, and the A* algorithm. The grids with numbers have been searched. You can compare the three efficiencies: 7. B* AlgorithmThe B* algorithm is a more efficient algorithm than the A* algorithm. It is suitable for automatic path finding of monsters in games. Its efficiency far exceeds that of the A* algorithm. After testing, the efficiency is dozens or hundreds of times that of the ordinary A* algorithm. I don't want to introduce the B* algorithm. Go to Google and search for it yourself. Through the continuous evolution of the above algorithms, we can see the limitations of each algorithm, as well as the solutions that emerge in the extended new algorithms. I hope it will facilitate your understanding. |
<<: Aiti Tribe Stories (24): Rooted in the technology circle, with a strong sense of belonging
>>: How to Evolve Neural Networks with Automatic Machine Learning
"Just search Baidu and you will know." ...
In the past two years, if we were to ask which tr...
In the era of comprehensive TV intelligence, the ...
The days when Apple's entire company's fa...
Perhaps in modern times when technology is more a...
Before the Spring Festival, the native promotion ...
The following is the latest traffic ranking of 59...
The Saudi stock market, which also traded on Sund...
What is the happiest thing in a day? Of course it...
For domestic Internet ToC applications, WeChat Mi...
Last night, when I returned to Beijing from a bus...
The Autumnal Equinox has arrived, indicating that...
During its long geological development and evolut...
[[405135]] I have recommended many useful mobile ...