Trying to implement A* pathfinding for a small game. Running into some strange bugs.
Code:
class PathNode
{
private:
const PathNode* parent;
GameObject position;
int g;
int h;
int f;
public:
PathNode(GameObject _position, int _g, int _h, const PathNode* _parent = nullptr) {
parent = _parent;
position = _position;
g = _g; // distance between the start node and the current node
h = _h; // distance between the current node and the end node
f = g + h; // Total cost of the node (g + h)
}
PathNode(const PathNode& other) {
position = other.position;
g = other.g; // distance between the start node and the current node
h = other.h; // distance between the current node and the end node
f = other.f; // Total cost of the node (g + h)
parent = other.parent;
}
bool operator==(const PathNode& other) const {
return (this->position == other.position);
}
bool operator!=(const PathNode& other) const {
return !operator==(other);
}
// GETTERS:
int getg() const;
int geth() const;
int getf() const;
const PathNode* getParent() const;
const GameObject getPosition() const;
// SETTERS:
void setg(int newG);
void seth(int newH);
void setf(int newF);
void setParent(const PathNode* newParent);
void setPosition(GameObject newPos);
};
And The PathFinding code:
char Ghost::aStar(char board[BoardYSize][BoardXSize], GameObject end) {
int startEndDistance = pow((getX() - end.getX()), 2) + pow((getY() - end.getY()), 2);
PathNode startNode(getPosition(), 0, startEndDistance); // in the ctor of PathNode, the default values of Parent == nullptr.
PathNode endNode(end, startEndDistance, 0); // in the ctor of PathNode, the default values of Parent == nullptr.
// Initialize both Open and Closed Lists:
vector<PathNode> openList;
vector<PathNode> closedList;
openList.reserve(500);
closedList.reserve(500);
// Add the StartNode:
openList.push_back(startNode);
// Loop until you find the end:
while (openList.size() > 0) {
// Get the current Node.
PathNode currentNode(openList[0]); // Default copy ctor.
int index = 0;
for (int i = 0; i < openList.size(); i++) {
if (openList[i].getf() < currentNode.getf()) {
index = i;
currentNode = openList[i];
}
}
// Pop Current off openList, and add to closedList:
openList.erase(openList.begin() + index);
closedList.push_back(currentNode);
// If found the end, return:
if (currentNode == endNode) {
// return direction of the first move of the path:
const PathNode* nextNode = ¤tNode;
const PathNode* firstMoveNode = nullptr;
while (*nextNode != startNode) {
firstMoveNode = nextNode;
nextNode = nextNode->getParent();
}
GameObject newPos = firstMoveNode->getPosition();
GameObject currentPos = startNode.getPosition();
if (newPos.getX() - currentPos.getX() == 0 && newPos.getY() - currentPos.getY() == 1)
return 'w';
else if (newPos.getX() - currentPos.getX() == 0 && newPos.getY() - currentPos.getY() == -1)
return 'x';
else if (newPos.getX() - currentPos.getX() == 1 && newPos.getY() - currentPos.getY() == 0)
return 'd';
else if (newPos.getX() - currentPos.getX() == -1 && newPos.getY() - currentPos.getY() == 0)
return 'a';
else
return 's';
}
// Generate Children:
vector <PathNode> children;
// temp is used to generate the children of the currentNode.
GameObject temp[4];
temp[0] = GameObject(0, 1); // Position above currentNode
temp[1] = GameObject(1, 0); // Position right of currentNode
temp[2] = GameObject(0, -1); // Position left of currentNode
temp[3] = GameObject(-1, 0); // Position below currentNode
for (int i = 0 ; i < 4; i++) {
// Get Node Position:
GameObject nodePosition(currentNode.getPosition() + temp[i]);
// Make Sure within Range of board & Not a Wall (walkable terrain):
if (!checkLegalMove(nodePosition, board))
continue;
PathNode newNode(nodePosition, 0, 0, ¤tNode);
children.push_back(newNode);
}
// Loop through Children:
for (auto child : children) {
bool addChild = true;
// Child is on the closedList:
for (auto closedChild : closedList) {
if (child == closedChild) {
addChild = false;
continue;
}
}
if (!addChild) continue;
// Create the G H and F values:
child.setg(currentNode.getg() + 1);
child.seth(pow((child.getPosition().getX() - endNode.getPosition().getX()), 2) + pow((child.getPosition().getY() - endNode.getPosition().getY()), 2));
child.setf(child.getg() + child.geth());
// Child is already in the openList:
for (auto openNode : openList) {
if (child == openNode && child.getg() > openNode.getg()) {
addChild = false;
continue;
}
}
if (!addChild) continue;
openList.push_back(child);
}
}
return 's';
}
My goal is to use A* to find a route and simply return the direction of the first position to travel to.
The Problem I run into: The problem is that when the condition of currentNode == endNode is met (reached the goal). Every PathNode's parent is simply a pointing to itself (according to the debugger). I don't understand why it's happening, I assume The current pointer gets destroyed at some point in time but i can't figure out why it's happening.