Using pass system for nodes instead of state field.
Housekeeping.
This commit is contained in:
@@ -51,6 +51,11 @@ func set_terrain(point: Vector2i, type: MultilevelAStarEx.TerrainType) -> void:
|
|||||||
_astar.set_terrain(point, type)
|
_astar.set_terrain(point, type)
|
||||||
|
|
||||||
|
|
||||||
|
func is_blocked(point: Vector2i) -> bool:
|
||||||
|
assert(_used_rect.has_point(point))
|
||||||
|
return (_astar.get_terrain(point) == MultilevelAStarEx.BLOCKED) or _astar.get_unit(point)
|
||||||
|
|
||||||
|
|
||||||
func find_path(from: Vector2i, to: Vector2i, return_closest: bool = false) -> Array[Vector2i]:
|
func find_path(from: Vector2i, to: Vector2i, return_closest: bool = false) -> Array[Vector2i]:
|
||||||
assert(_used_rect.has_point(from))
|
assert(_used_rect.has_point(from))
|
||||||
assert(_used_rect.has_point(to))
|
assert(_used_rect.has_point(to))
|
||||||
|
|||||||
@@ -17,18 +17,23 @@ using namespace godot;
|
|||||||
static const int STRAIGHT_DISTANCE = 10;
|
static const int STRAIGHT_DISTANCE = 10;
|
||||||
static const int DIAGONAL_DISTANCE = 14;
|
static const int DIAGONAL_DISTANCE = 14;
|
||||||
|
|
||||||
Node::Node() { }
|
Node::Node()
|
||||||
|
{
|
||||||
|
this->openPass = 0;
|
||||||
|
this->closedPass = 0;
|
||||||
|
}
|
||||||
|
|
||||||
Node::Node(int x, int y)
|
Node::Node(int x, int y) : Node()
|
||||||
{
|
{
|
||||||
this->x = x;
|
this->x = x;
|
||||||
this->y = y;
|
this->y = y;
|
||||||
this->state = UNUSED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::init(Node *parent, int distanceFromStart, const Vector2i &end)
|
void Node::open(int pass, Node *parent, int distanceFromStart, const Vector2i &end)
|
||||||
{
|
{
|
||||||
this->state = OPEN;
|
DEV_ASSERT(this->openPass != pass);
|
||||||
|
|
||||||
|
this->openPass = pass;
|
||||||
this->parent = parent;
|
this->parent = parent;
|
||||||
this->distanceFromStart = distanceFromStart;
|
this->distanceFromStart = distanceFromStart;
|
||||||
|
|
||||||
@@ -58,6 +63,29 @@ void Node::init(Node *parent, int distanceFromStart, const Vector2i &end)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Node::close(int pass)
|
||||||
|
{
|
||||||
|
DEV_ASSERT(openPass == pass && closedPass != pass);
|
||||||
|
|
||||||
|
closedPass = pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node::NodeState Node::state(int pass) const
|
||||||
|
{
|
||||||
|
if (closedPass == pass)
|
||||||
|
{
|
||||||
|
return CLOSED;
|
||||||
|
}
|
||||||
|
else if (openPass == pass)
|
||||||
|
{
|
||||||
|
return OPEN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return UNUSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int Node::total_cost() const
|
int Node::total_cost() const
|
||||||
{
|
{
|
||||||
return distanceFromStart + distanceToEnd;
|
return distanceFromStart + distanceToEnd;
|
||||||
@@ -83,6 +111,7 @@ MultilevelAStarEx::MultilevelAStarEx()
|
|||||||
//UtilityFunctions::print("Constructor.");
|
//UtilityFunctions::print("Constructor.");
|
||||||
|
|
||||||
_init = false;
|
_init = false;
|
||||||
|
_pass = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
MultilevelAStarEx::~MultilevelAStarEx()
|
MultilevelAStarEx::~MultilevelAStarEx()
|
||||||
@@ -211,29 +240,27 @@ Variant MultilevelAStarEx::find_path(const Vector2i &from, const Vector2i &to, b
|
|||||||
DEV_ASSERT(_region.has_point(from));
|
DEV_ASSERT(_region.has_point(from));
|
||||||
DEV_ASSERT(_region.has_point(to));
|
DEV_ASSERT(_region.has_point(to));
|
||||||
|
|
||||||
|
_pass++;
|
||||||
|
|
||||||
Vector2i from2 = from - _trans;
|
Vector2i from2 = from - _trans;
|
||||||
Vector2i to2 = to - _trans;
|
Vector2i to2 = to - _trans;
|
||||||
|
|
||||||
Variant result;
|
|
||||||
|
|
||||||
std::vector<Node *> open;
|
std::vector<Node *> open;
|
||||||
std::vector<Node*> closed;
|
|
||||||
|
|
||||||
open.reserve(_width * _height);
|
open.reserve(_width * _height);
|
||||||
closed.reserve(_width * _height);
|
|
||||||
|
|
||||||
Node *closest = &NODES(from2.x, from2.y);
|
Node *closest = &NODES(from2.x, from2.y);
|
||||||
closest->init(nullptr, 0, to2);
|
closest->open(_pass, nullptr, 0, to2);
|
||||||
open.push_back(closest);
|
open.push_back(closest);
|
||||||
|
|
||||||
auto process = [this, &open, &closed, &to2, &closest](Node *current, int x, int y, int distance) {
|
auto process = [this, &open, &to2, &closest](Node *current, int x, int y, int distance) {
|
||||||
Node *node = &NODES(x, y);
|
Node *node = &NODES(x, y);
|
||||||
if (node->state == Node::UNUSED)
|
if (node->state(_pass) == Node::UNUSED)
|
||||||
{
|
{
|
||||||
node->init(current, current->distanceFromStart + distance, to2);
|
node->open(_pass, current, current->distanceFromStart + distance, to2);
|
||||||
open.push_back(node);
|
open.push_back(node);
|
||||||
}
|
}
|
||||||
else if (node->state == Node::OPEN)
|
else if (node->state(_pass) == Node::OPEN)
|
||||||
{
|
{
|
||||||
if (current->distanceFromStart < node->parent->distanceFromStart)
|
if (current->distanceFromStart < node->parent->distanceFromStart)
|
||||||
{
|
{
|
||||||
@@ -256,7 +283,7 @@ Variant MultilevelAStarEx::find_path(const Vector2i &from, const Vector2i &to, b
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
while (open.size() > 0)
|
while (!open.empty())
|
||||||
{
|
{
|
||||||
// find closest to destination
|
// find closest to destination
|
||||||
Node *current = open[0];
|
Node *current = open[0];
|
||||||
@@ -271,14 +298,12 @@ Variant MultilevelAStarEx::find_path(const Vector2i &from, const Vector2i &to, b
|
|||||||
if (current->distanceToEnd == 0)
|
if (current->distanceToEnd == 0)
|
||||||
{
|
{
|
||||||
// found the path
|
// found the path
|
||||||
result = Variant(generate_path(current));
|
return Variant(generate_path(current));
|
||||||
goto cleanup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// close it
|
// close it
|
||||||
current->state = Node::CLOSED;
|
current->close(_pass);
|
||||||
open.erase(std::remove(open.begin(), open.end(), current), open.end());
|
open.erase(std::remove(open.begin(), open.end(), current), open.end());
|
||||||
closed.push_back(current);
|
|
||||||
|
|
||||||
// expand it
|
// expand it
|
||||||
if (current->x - 1 >= 0) // left
|
if (current->x - 1 >= 0) // left
|
||||||
@@ -339,23 +364,11 @@ Variant MultilevelAStarEx::find_path(const Vector2i &from, const Vector2i &to, b
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is skipped if a path was found
|
|
||||||
if (return_closest)
|
if (return_closest)
|
||||||
{
|
{
|
||||||
// return path to closest
|
// return path to closest
|
||||||
result = Variant(generate_path(closest));
|
return Variant(generate_path(closest));
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
return Variant();
|
||||||
// release the nodes
|
|
||||||
for (Node *node : open)
|
|
||||||
{
|
|
||||||
node->state = Node::UNUSED;
|
|
||||||
}
|
|
||||||
for (Node *node : closed)
|
|
||||||
{
|
|
||||||
node->state = Node::UNUSED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NodeState state;
|
int openPass, closedPass;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
Node *parent;
|
Node *parent;
|
||||||
@@ -30,7 +30,9 @@ private:
|
|||||||
int distanceToEndForClosest;
|
int distanceToEndForClosest;
|
||||||
|
|
||||||
Node(int x, int y);
|
Node(int x, int y);
|
||||||
void init(Node *parent, int distanceFromStart, const Vector2i &end);
|
void open(int pass, Node *parent, int distanceFromStart, const Vector2i &end);
|
||||||
|
void close(int pass);
|
||||||
|
NodeState state(int pass) const;
|
||||||
int total_cost() const;
|
int total_cost() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -51,6 +53,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool _init;
|
bool _init;
|
||||||
|
int _pass;
|
||||||
std::vector<TerrainType> _terrain;
|
std::vector<TerrainType> _terrain;
|
||||||
std::vector<bool> _units;
|
std::vector<bool> _units;
|
||||||
std::vector<Node> _nodes;
|
std::vector<Node> _nodes;
|
||||||
|
|||||||
Reference in New Issue
Block a user