diff --git a/aStar/App.cpp b/aStar/App.cpp index 8e21ca9..d167f8d 100644 --- a/aStar/App.cpp +++ b/aStar/App.cpp @@ -30,8 +30,14 @@ void App::Input() { if (event.type == sf::Event::Closed) window->close(); if (event.type == sf::Event::KeyPressed) { - if (event.key.code == sf::Keyboard::Space) { - + if (event.key.code == sf::Keyboard::Q) { + explorer->setDestination(sf::Vector2i(20, 20)); + } + if (event.key.code == sf::Keyboard::W) { + explorer->setDestination(sf::Vector2i(200, 200)); + } + if (event.key.code == sf::Keyboard::E) { + explorer->setDestination(sf::Vector2i(100, 12)); } } } @@ -39,6 +45,7 @@ void App::Input() { void App::Update(double step_size) { Input(); + explorer->move(); } void App::Render() { @@ -91,7 +98,7 @@ void App::Render() { } } - // Draw the player + // Draw the explorer for (int x2 = 1; x2 < 5; x2++) { for (int y2 = 1; y2 < 5; y2++) { diff --git a/aStar/App.h b/aStar/App.h index 9c43953..d9754d8 100644 --- a/aStar/App.h +++ b/aStar/App.h @@ -3,6 +3,16 @@ #include "Map.h" #include "Explorer.h" +template +class MultiArray { +private: + typedef T cols[height]; + cols * data; +public: + T& operator() (int x, int y) { return data[x][y]; } + MultiArray() { data = new cols[width]; } + ~MultiArray() { delete[] data; } +}; class App { public: // Constants diff --git a/aStar/Explorer.cpp b/aStar/Explorer.cpp index f6c2028..6de2b8b 100644 --- a/aStar/Explorer.cpp +++ b/aStar/Explorer.cpp @@ -1,9 +1,10 @@ #include "Explorer.h" #include +#include "Pather.h" Explorer::Explorer(Map* map_) { color = sf::Color::Blue; - position = sf::Vector2i(10, 10); + position = sf::Vector2i(6, 10); map = map_; } @@ -19,34 +20,41 @@ sf::Color Explorer::getColor() { return color; } + +void Explorer::setDestination(sf::Vector2i destination_) { + plan(destination_); +} + bool Explorer::move() { // While there are moves for us to take if (!movement_stack.empty()) { bool valid = false; // If the next move is valid, collision - int x = movement_stack.top(); + int x = movement_stack.back(); switch (x) { + case 0: + break; - case 0: // North + case 1: // North if (!map->getTile(position.x, position.y - 1)->isSolid()) { valid = true; position = sf::Vector2i(position.x, position.y - 1); } break; - case 1: // East + case 2: // East if (!map->getTile(position.x + 1, position.y)->isSolid()) { valid = true; position = sf::Vector2i(position.x + 1, position.y); } break; - case 2: // South + case 3: // South if (!map->getTile(position.x, position.y + 1)->isSolid()) { valid = true; position = sf::Vector2i(position.x, position.y + 1); } break; - case 3: // West + case 4: // West if (!map->getTile(position.x - 1, position.y)->isSolid()) { valid = true; position = sf::Vector2i(position.x - 1, position.y); @@ -58,14 +66,14 @@ bool Explorer::move() { if (!valid) { std::cout << "Path blocked" << std::endl; // Flush the moves list - while(!movement_stack.empty()) { - movement_stack.pop(); + while (!movement_stack.empty()) { + movement_stack.pop_back(); } return false; } // If everything went well, pop and return true - movement_stack.pop(); + movement_stack.pop_back(); return true; } else @@ -74,7 +82,8 @@ bool Explorer::move() { // A* bool Explorer::plan(sf::Vector2i destination_) { - + Pather pather(map); + movement_stack = pather.pathTo(position, destination_); return true; } diff --git a/aStar/Explorer.h b/aStar/Explorer.h index 3af0a1b..ab60720 100644 --- a/aStar/Explorer.h +++ b/aStar/Explorer.h @@ -9,13 +9,14 @@ public: ~Explorer(); sf::Vector2i getPosition(); sf::Color getColor(); + void setDestination(sf::Vector2i destination_); + bool move(); private: sf::Color color; sf::Vector2i position; Map* map; - std::stack movement_stack; - bool move(); + std::deque movement_stack; bool plan(sf::Vector2i destination_); }; diff --git a/aStar/Map.cpp b/aStar/Map.cpp index 236535c..e646991 100644 --- a/aStar/Map.cpp +++ b/aStar/Map.cpp @@ -22,8 +22,8 @@ Tile* Map::getTile(sf::Vector2i position_) { } bool Map::isTileSolid(sf::Vector2i position_) { - if (position_.x > CELLS_WIDTH || position_.x < 0 - || position_.y > CELLS_HEIGHT || position_.y < 0) { + if (position_.x >= CELLS_WIDTH || position_.x < 0 + || position_.y >= CELLS_HEIGHT || position_.y < 0) { return true; } else @@ -44,7 +44,7 @@ void Map::Init() { for (int x = 0; x < CELLS_WIDTH; x++) { for (int y = 0; y < CELLS_HEIGHT; y++) { q = rand() % 100; - if (q > 70) { + if (q > 90) { tileArray[x][y] = new Tile(true, 100.0, sf::Color::Cyan); } else { diff --git a/aStar/Pather.cpp b/aStar/Pather.cpp index a2e09e0..3b616d6 100644 --- a/aStar/Pather.cpp +++ b/aStar/Pather.cpp @@ -1,7 +1,7 @@ #include "Pather.h" #include -node::node(sf::Vector2i XY, int h, int cF, int cL, node* p, Pather* pather_) { +node::node(sf::Vector2i XY, double h, int cF, int cL, node* p, Pather* pather_) { xy = XY; hueristic = h; cameFrom = cF; @@ -22,7 +22,7 @@ void node::neighbors() { int y = pather->getEndNodePosition().y; sf::Vector2i dest0XY(xy.x, xy.y - 1); // North - if (!pather->map->isTileSolid(dest0XY) && pather->visitedMap[dest0XY.x][dest0XY.y] != 1) { + if (!pather->map->isTileSolid(dest0XY) && pather->visitedMap(dest0XY.x, dest0XY.y) != 1) { // If so, find the distance between this node and the end node, the hueristic int tempx = (x - dest0XY.x); int tempy = (y - dest0XY.y); @@ -30,17 +30,17 @@ void node::neighbors() { // I think dv is the hueristic?? double dv = sqrt((tempx * tempx) + (tempy * tempy)); - int v = static_cast(dv); + double v = dv; // Take that value and create a new node - pather->openList.emplace(new node(dest0XY, v, 0, 1, pather->active_node, pather), v); + pather->openList.emplace(new node(dest0XY, v, 3, 1, pather->active_node, pather), v); // Set that tile as visited so we don't get stuck in a loop - pather->visitedMap[dest0XY.x][dest0XY.y] = 1; + pather->visitedMap(dest0XY.x, dest0XY.y) = 1; } sf::Vector2i dest1XY(xy.x + 1, xy.y); // East - if (!pather->map->isTileSolid(dest1XY) && pather->visitedMap[dest1XY.x][dest1XY.y] != 1) { + if (!pather->map->isTileSolid(dest1XY) && pather->visitedMap(dest1XY.x, dest1XY.y) != 1) { // If so, find the distance between this node and the end node, the hueristic int tempx = (x - dest1XY.x); int tempy = (y - dest1XY.y); @@ -48,17 +48,17 @@ void node::neighbors() { // I think dv is the hueristic?? double dv = sqrt((tempx * tempx) + (tempy * tempy)); - int v = static_cast(dv); + double v = dv; // Take that value and create a new node - pather->openList.emplace(new node(dest1XY, v, 0, 1, pather->active_node, pather), v); + pather->openList.emplace(new node(dest1XY, v, 4, 1, pather->active_node, pather), v); // Set that tile as visited so we don't get stuck in a loop - pather->visitedMap[dest1XY.x][dest1XY.y] = 1; + pather->visitedMap(dest1XY.x, dest1XY.y) = 1; } sf::Vector2i dest2XY(xy.x, xy.y + 1); // South - if (!pather->map->isTileSolid(dest2XY) && pather->visitedMap[dest2XY.x][dest2XY.y] != 1) { + if (!pather->map->isTileSolid(dest2XY) && pather->visitedMap(dest2XY.x, dest2XY.y) != 1) { // If so, find the distance between this node and the end node, the hueristic int tempx = (x - dest2XY.x); int tempy = (y - dest2XY.y); @@ -66,17 +66,17 @@ void node::neighbors() { // I think dv is the hueristic?? double dv = sqrt((tempx * tempx) + (tempy * tempy)); - int v = static_cast(dv); + double v = dv; // Take that value and create a new node - pather->openList.emplace(new node(dest2XY, v, 0, 1, pather->active_node, pather), v); + pather->openList.emplace(new node(dest2XY, v, 1, 1, pather->active_node, pather), v); // Set that tile as visited so we don't get stuck in a loop - pather->visitedMap[dest2XY.x][dest2XY.y] = 1; + pather->visitedMap(dest2XY.x, dest2XY.y) = 1; } sf::Vector2i dest3XY(xy.x - 1, xy.y); // West - if (!pather->map->isTileSolid(dest3XY) && pather->visitedMap[dest3XY.x][dest3XY.y] != 1) { + if (!pather->map->isTileSolid(dest3XY) && pather->visitedMap(dest3XY.x, dest3XY.y) != 1) { // If so, find the distance between this node and the end node, the hueristic int tempx = (x - dest3XY.x); int tempy = (y - dest3XY.y); @@ -84,13 +84,13 @@ void node::neighbors() { // I think dv is the hueristic?? double dv = sqrt((tempx * tempx) + (tempy * tempy)); - int v = static_cast(dv); + double v = dv; // Take that value and create a new node - pather->openList.emplace(new node(dest3XY, v, 0, 1, pather->active_node, pather), v); + pather->openList.emplace(new node(dest3XY, v, 2, 1, pather->active_node, pather), v); // Set that tile as visited so we don't get stuck in a loop - pather->visitedMap[dest3XY.x][dest3XY.y] = 1; + pather->visitedMap(dest3XY.x, dest3XY.y) = 1; } } @@ -98,6 +98,7 @@ void node::neighbors() { Pather::Pather(Map* map_) { map = map_; + //visitedMap = new MultiArray(); } Pather::~Pather() { @@ -109,15 +110,18 @@ sf::Vector2i Pather::getEndNodePosition() { std::deque Pather::pathTo(sf::Vector2i start, sf::Vector2i end) { + // Clear the visited map for erroneous data for (int i = 0; i < Map::CELLS_WIDTH; i++) { for (int l = 0; l < Map::CELLS_HEIGHT; l++) { - visitedMap[i][l] = 0; + visitedMap(i, l) = 0; } } + + std::cout << visitedMap(10, 163); // Place the start and end nodes - start_node = new node(start, 0, 0, 0, nullptr, this); + start_node = new node(start, 7000, 0, 0, nullptr, this); end_node = new node(end, 0, 0, 0, nullptr, this); // Set the entry point, clean up any stray data from last run @@ -126,7 +130,7 @@ std::deque Pather::pathTo(sf::Vector2i start, sf::Vector2i end) { closedList.clear(); // Seed for the loop - openList.emplace(start_node, 0); + openList.emplace(start_node, start_node->hueristic); early_exit = false; path_list = loop(); @@ -136,26 +140,34 @@ std::deque Pather::pathTo(sf::Vector2i start, sf::Vector2i end) { std::deque Pather::loop() { - while (!openList.empty() && !early_exit) { + + // Damn thing keeps falling out of scope + + + while (!openList.empty() && !early_exit) { // Early exit jankyness, need to change this - if (closedList.size() > 3000) { - no_path = true; - early_exit = true; - break; - } - else if (active_node->xy.x == end_node->xy.x && end_node->xy.y == end_node->xy.y) { + //if (closedList.size() > 3000) { + // no_path = true; + // early_exit = true; + // break; + //} + if (active_node->xy.x == end_node->xy.x && active_node->xy.y == end_node->xy.y) { early_exit = true; break; } else { // Find the pair with the lowest hueristic - // 5/10 - std::pair bestMin; + // 5/10 + std::pair bestMin(start_node, 10000); + for (auto testMin: openList) { - if (bestMin.second < testMin.second) + if (bestMin.second >= testMin.second) bestMin = testMin; } + // Set the new active node to the lowest hueristic that we found earlier + active_node = bestMin.first; + // Find the neighbors for that node active_node->neighbors(); @@ -163,12 +175,11 @@ std::deque Pather::loop() { openList.erase(active_node); // Check to see if the node has already been added to the closed list, if not, add it - if (closedList.count(active_node) > 0) { + if (closedList.count(active_node) == 0) { closedList.emplace(active_node, active_node->hueristic); } - // Set the new active node to the lowest hueristic that we found earlier - active_node = bestMin.first; + } } @@ -184,10 +195,12 @@ std::deque Pather::loop() { std::deque Pather::returnPath() { std::deque path; - while (active_node != nullptr) { + while (active_node->parent != nullptr) { path.push_back(active_node->cameFrom); + + node* parent = active_node->parent; delete active_node; - active_node = active_node->parent; + active_node = parent; } return path; diff --git a/aStar/Pather.h b/aStar/Pather.h index ab2a681..57141ef 100644 --- a/aStar/Pather.h +++ b/aStar/Pather.h @@ -8,7 +8,7 @@ class Pather; class node { public: - node(sf::Vector2i XY, int h, int cF, int cL, node* p, Pather* pather_); + node(sf::Vector2i XY, double h, int cF, int cL, node* p, Pather* pather_); node(); ~node(); @@ -16,7 +16,7 @@ public: // Ugh, pointers, ugh c++ node* parent; - int hueristic; + double hueristic; int cameFrom; int closedList; Pather* pather; @@ -33,15 +33,17 @@ public: Map* map; - std::unordered_map openList; - std::unordered_map closedList; - int visitedMap[App::WINDOW_HEIGHT][App::WINDOW_WIDTH]; - - std::deque pathTo(sf::Vector2i start, sf::Vector2i end); - std::deque loop(); - std::deque returnPath(); - - sf::Vector2i getEndNodePosition(); + std::unordered_map openList; + std::unordered_map closedList; + + MultiArray visitedMap; + //int visitedMap[App::WINDOW_HEIGHT][App::WINDOW_WIDTH]; + + std::deque pathTo(sf::Vector2i start, sf::Vector2i end); + std::deque loop(); + std::deque returnPath(); + + sf::Vector2i getEndNodePosition(); node* start_node; node* active_node; diff --git a/aStar/node.cpp b/aStar/node.cpp new file mode 100644 index 0000000..6a7e3f1 --- /dev/null +++ b/aStar/node.cpp @@ -0,0 +1,95 @@ +#pragma once +#include "node.h" + +node::node(sf::Vector2i XY, int h, int cF, int cL, node* p, Pather* pather_) { + xy = XY; + hueristic = h; + cameFrom = cF; + closedList = cL; + parent = p; + pather = pather_; +} +node::node() { + +} +node::~node() { + +} + +void node::neighbors() { + + int x = pather->getEndNodePosition().x; + int y = pather->getEndNodePosition().y; + + sf::Vector2i dest0XY(xy.x, xy.y - 1); // North + if (!pather->map->isTileSolid(dest0XY) && pather->visitedMap[dest0XY.x][dest0XY.y] != 1) { + // If so, find the distance between this node and the end node, the hueristic + int tempx = (x - dest0XY.x); + int tempy = (y - dest0XY.y); + + // I think dv is the hueristic?? + double dv = sqrt((tempx * tempx) + (tempy * tempy)); + + int v = static_cast(dv); + + // Take that value and create a new node + pather->openList.emplace(new node(dest0XY, v, 0, 1, pather->active_node, pather), v); + + // Set that tile as visited so we don't get stuck in a loop + pather->visitedMap[dest0XY.x][dest0XY.y] = 1; + } + + sf::Vector2i dest1XY(xy.x + 1, xy.y); // East + if (!pather->map->isTileSolid(dest1XY) && pather->visitedMap[dest1XY.x][dest1XY.y] != 1) { + // If so, find the distance between this node and the end node, the hueristic + int tempx = (x - dest1XY.x); + int tempy = (y - dest1XY.y); + + // I think dv is the hueristic?? + double dv = sqrt((tempx * tempx) + (tempy * tempy)); + + int v = static_cast(dv); + + // Take that value and create a new node + pather->openList.emplace(new node(dest1XY, v, 0, 1, pather->active_node, pather), v); + + // Set that tile as visited so we don't get stuck in a loop + pather->visitedMap[dest1XY.x][dest1XY.y] = 1; + } + + sf::Vector2i dest2XY(xy.x, xy.y + 1); // South + if (!pather->map->isTileSolid(dest2XY) && pather->visitedMap[dest2XY.x][dest2XY.y] != 1) { + // If so, find the distance between this node and the end node, the hueristic + int tempx = (x - dest2XY.x); + int tempy = (y - dest2XY.y); + + // I think dv is the hueristic?? + double dv = sqrt((tempx * tempx) + (tempy * tempy)); + + int v = static_cast(dv); + + // Take that value and create a new node + pather->openList.emplace(new node(dest2XY, v, 0, 1, pather->active_node, pather), v); + + // Set that tile as visited so we don't get stuck in a loop + pather->visitedMap[dest2XY.x][dest2XY.y] = 1; + } + + sf::Vector2i dest3XY(xy.x - 1, xy.y); // West + if (!pather->map->isTileSolid(dest3XY) && pather->visitedMap[dest3XY.x][dest3XY.y] != 1) { + // If so, find the distance between this node and the end node, the hueristic + int tempx = (x - dest3XY.x); + int tempy = (y - dest3XY.y); + + // I think dv is the hueristic?? + double dv = sqrt((tempx * tempx) + (tempy * tempy)); + + int v = static_cast(dv); + + // Take that value and create a new node + pather->openList.emplace(new node(dest3XY, v, 0, 1, pather->active_node, pather), v); + + // Set that tile as visited so we don't get stuck in a loop + pather->visitedMap[dest3XY.x][dest3XY.y] = 1; + } +} \ No newline at end of file diff --git a/aStar/node.h b/aStar/node.h new file mode 100644 index 0000000..5a56aed --- /dev/null +++ b/aStar/node.h @@ -0,0 +1,26 @@ +#pragma once +#include +#include "App.h" + +class node { +public: + + node(sf::Vector2i XY, int h, int cF, int cL, node* p, Pather* pather_); + node(); + ~node(); + + sf::Vector2i xy; + + // Ugh, pointers, ugh c++ + node* parent; + int hueristic; + int cameFrom; + int closedList; + Pather* pather; + + void neighbors(); +private: + +}; + +