From a59492b229f244b542d683747daafce13b88a38b Mon Sep 17 00:00:00 2001 From: Katja Date: Thu, 6 Jun 2024 00:02:18 +0200 Subject: [PATCH] Using std::set to sort nodes. --- demo/main.gd | 2 +- src/MultilevelAStarEx.cpp | 76 +++++++++++++++++++++++---------------- src/MultilevelAStarEx.h | 2 ++ 3 files changed, 48 insertions(+), 32 deletions(-) diff --git a/demo/main.gd b/demo/main.gd index eef3ca3..ba875fa 100644 --- a/demo/main.gd +++ b/demo/main.gd @@ -61,7 +61,7 @@ func find_path() -> void: var arr = astar.find_path(from, to, check_box.button_pressed) # vrne Variant: null ali Array #print(arr) - print(arr.size()) + #print(arr.size()) if arr.size() > 1: # if the start and the end are the same there is no line to draw # add new path diff --git a/src/MultilevelAStarEx.cpp b/src/MultilevelAStarEx.cpp index d2451a4..de07a78 100644 --- a/src/MultilevelAStarEx.cpp +++ b/src/MultilevelAStarEx.cpp @@ -4,9 +4,7 @@ #include #include -#include -#include -#include +#include #define TERRAIN(x, y) (_terrain[(x) + (y) * _width]) #define UNITS(x, y) (_units[(x) + (y) * _width]) @@ -91,6 +89,33 @@ int Node::total_cost() const return distanceFromStart + distanceToEnd; } +bool Node::compare_nodes(const Node *left, const Node *right) { + if (left->total_cost() < right->total_cost()) + { + return true; + } + else if (left->total_cost() > right->total_cost()) + { + return false; + } + else // if (left->total_cost() == right->total_cost()) + { + if (left->distanceToEnd < right->distanceToEnd) + { + return true; + } + else if (left->distanceToEnd > right->distanceToEnd) + { + return false; + } + else // if (left->distanceToEnd == right->distanceToEnd) + { + // make sure no two nodes are the same + return left < right; + } + } +} + void MultilevelAStarEx::_bind_methods() { ClassDB::bind_method(D_METHOD("init", "region"), &MultilevelAStarEx::init); @@ -114,10 +139,7 @@ MultilevelAStarEx::MultilevelAStarEx() _pass = 0; } -MultilevelAStarEx::~MultilevelAStarEx() -{ - //UtilityFunctions::print("Destructor."); -} +MultilevelAStarEx::~MultilevelAStarEx() { } void MultilevelAStarEx::init(const Rect2i ®ion) { @@ -251,30 +273,34 @@ TypedArray MultilevelAStarEx::find_path(const Vector2i &from, const Ve Vector2i from2 = from - _trans; Vector2i to2 = to - _trans; - std::vector open; - - open.reserve(_width * _height); + std::set open(&Node::compare_nodes); Node *closest = &NODES(from2.x, from2.y); closest->open(_pass, nullptr, 0, to2); - open.push_back(closest); + open.insert(closest); auto process = [this, &open, &to2, &closest](Node *current, int x, int y, int distance) { Node *node = &NODES(x, y); - if (node->state(_pass) == Node::UNUSED) - { - node->open(_pass, current, current->distanceFromStart + distance, to2); - open.push_back(node); - } - else if (node->state(_pass) == Node::CLOSED) + if (node->state(_pass) == Node::CLOSED) { return; } + else if (node->state(_pass) == Node::UNUSED) + { + node->open(_pass, current, current->distanceFromStart + distance, to2); + open.insert(node); + } else if (current->distanceFromStart + distance < node->distanceFromStart) { + auto nodeIter = open.find(node); + DEV_ASSERT(nodeIter != open.end()); + open.erase(nodeIter); + node->parent = current; node->distanceFromStart = current->distanceFromStart + distance; + + open.insert(node); } // find the closest cell @@ -293,19 +319,7 @@ TypedArray MultilevelAStarEx::find_path(const Vector2i &from, const Ve while (!open.empty()) { - // find closest to destination - Node *current = open[0]; - for (Node *n : open) - { - if (n->total_cost() < current->total_cost()) - { - current = n; - } - else if ((n->total_cost() == current->total_cost()) && (n->distanceToEnd < current->distanceToEnd)) - { - current = n; - } - } + Node *current = *open.begin(); if (current->distanceToEnd == 0) { @@ -314,8 +328,8 @@ TypedArray MultilevelAStarEx::find_path(const Vector2i &from, const Ve } // close it + open.erase(open.begin()); current->close(_pass); - open.erase(std::remove(open.begin(), open.end(), current), open.end()); // expand it if (current->x - 1 >= 0) // left diff --git a/src/MultilevelAStarEx.h b/src/MultilevelAStarEx.h index 58fa220..16b0bf6 100644 --- a/src/MultilevelAStarEx.h +++ b/src/MultilevelAStarEx.h @@ -29,6 +29,8 @@ private: int distanceToEndForClosest; + static bool compare_nodes(const Node *left, const Node *right); + Node(int x, int y); void open(int pass, Node *parent, int distanceFromStart, const Vector2i &end); void close(int pass);