top of page
Artboard 1cv_img_bg1.png

code samples

Pathfinding A*

  • Foto del escritor: Emilia Paredes
    Emilia Paredes
  • 24 feb 2021
  • 3 Min. de lectura

Pathfinding is the computational plotting of the shortest route between two points. A* is a pathfinding graph traversal algorithm widely used all through programming sectors due to its completeness, optimality, and optimal efficiency.



/*!
 * \brief Runs A Star pathfinding algorithm
 * \param start - start position, end - end (target) position
 * \return true if achivable, false otherwise
 */
bool A_Star::Run(const A_Vec2& start, const A_Vec2& end)
{
	//set final and start node
	m_final_node = end;
	m_start_node = start;
	//start node
	A_Node start_node{};
	start_node.m_position = start;
	//push start node to the open list
	// the start cost set by the heuristic function
	float start_cost = GetHeuristic(start_node.m_position);
	//set the initial cost to 0
	start_node.m_cost = 0.0f;
	//accumulative cost
	start_node.m_total = start_cost;
	//check if we can go in straight line (optimization)
	if (m_start_node == m_final_node || (m_straight_line && IsStraightLine(m_start_node, m_final_node))) {
		//push the node to the closed list
		m_closed_list.push_back(start_node);
		//set the predecesor of the node as the position
		start_node.m_parent = start_node.m_position;
		//set the current position of the node to the final (goal) position
		start_node.m_position = m_final_node;
		//push the visited node to the closed list
		m_closed_list.push_back(start_node);
		//since the path was found, then return true.
		return true;
	}
	//since we cant get in a stright line, push start node to the open list.
	pushOpen(start_node);
	//allocate memory for the closed and open list
	m_open_list.reserve(  terrain_width * 2);
	m_closed_list.reserve(terrain_width * 2);
	//loop through the open list until its empty
	while (!m_open_list.empty()) {
		//get the current node to check
		A_Node current_node = popOpen();
		//check if it is the end
		if (current_node.m_position == m_final_node){
			//push last node
			m_closed_list.push_back(current_node);
			//return true, we found a path
			PaintLists();
			return true;
		}
		//check if node is in closed list then we do not visit it again
		if (InClosedList(current_node))
			continue;

		//get neighbour nodes (within terrain bounds)
		const int end_r = ((current_node.m_position.first < terrain_width) ? 1 : 0);
		const int end_c = ((current_node.m_position.second < terrain_width) ? 1 : 0);

		//loop through the neighbour cells
		for (int r = ((current_node.m_position.first < 1) ? 0 : -1); r <= end_r; r++) {
			for (int c = ((current_node.m_position.second < 1) ? 0 : -1); c <= end_c; c++) {
				//to not check current cell
				if (r == 0 && c == 0)
					continue;
				//get neighbour positions
				const int neigh_r = current_node.m_position.first + r;
				const int neigh_c = current_node.m_position.second + c;
				//cehck if wall, do nothing since it is not a viable node
				if (g_terrain.IsWall(neigh_r, neigh_c))
					continue;
				//check if it is diagonal
				const bool is_diagonal = std::abs(c) + std::abs(r) > 1;
				//if there is a wall in the middle of the diagonal, not a valid path
				if (is_diagonal && (g_terrain.IsWall(current_node.m_position.first, neigh_c) ||
					g_terrain.IsWall(neigh_r, current_node.m_position.second)))
					continue;

				//push neighbour to open list
				A_Node neighbour{};
				//set position as row and column in terrain
				neighbour.m_position = { neigh_r, neigh_c };
				//check if node is diagonal (and possible path) and set pertinent cost
				if (is_diagonal)
					neighbour.m_cost = current_node.m_cost + sqrt_2;
				else
					neighbour.m_cost += current_node.m_cost;
				//increase influence cost depending on the terrain cell value
				float influence = 0.0f;
				if (m_analysis)
					influence += g_terrain.GetInfluenceMapValue(neigh_r, neigh_c);
				//calculate heuristic cost
				const float heuristic = GetHeuristic(neighbour.m_position);
				//set up total cost of neighbour's path
				neighbour.m_total = neighbour.m_cost + heuristic + influence;
				//set up path hierarchy
				neighbour.m_parent = current_node.m_position;
				//update cost and path hierarchy if node is already in closed list
				//but current cost is better.
				if (InClosedList(m_position) && m_closed_list[current_node].m_total > neighbour.m_total)
					m_closed_list.erase(m_closed_list.begin() + current_node.m_position);
				//push it to the open list
				pushOpen(neighbour);
			}
		}

		//push current to closed list
		m_closed_list.push_back(current_node);
	}
	//path found 
	return true;
}


 
 
 

Entradas recientes

Ver todo
Inverse Kinematics

Inverse Kinematics is the mathematical process of calculating the variable joint parameters needed to place the end of a kinematic shain,...

 
 
 

Comentarios


bottom of page