diff --git a/cpp/src/pathfinder.hpp b/cpp/src/pathfinder.hpp index 4d22178..12f5add 100644 --- a/cpp/src/pathfinder.hpp +++ b/cpp/src/pathfinder.hpp @@ -1,14 +1,45 @@ #pragma once #include +#include #include "math.hpp" +#include "map.hpp" namespace pathfinder { - using Path = std::vector; +using Path = std::vector; - class PathFinderBase { +enum class PathFinderType { + LINEAR = 1, + BFS, + COUNT, +}; - }; -} +class PathFinderBase { +public: + PathFinderBase() = default; + ~PathFinderBase() = default; + + PathFinderBase(const PathFinderBase&) = delete; + PathFinderBase(PathFinderBase&&) = delete; + PathFinderBase& operator=(const PathFinderBase&) = delete; + PathFinderBase& operator=(PathFinderBase&&) = delete; + + void SetMap(std::shared_ptr map); + virtual Path CalculatePath(WorldPos target) = 0; + +private: + std::shared_ptr m_Map; +}; + + +class LinearPathFinder : public PathFinderBase { + Path CalculatePath(WorldPos target) override; +}; + +std::unique_ptr create(PathFinderType type); + + +} // pathfinder namespace + diff --git a/cpp/src/pathfindingdemo.cpp b/cpp/src/pathfindingdemo.cpp index e704730..d22f89a 100644 --- a/cpp/src/pathfindingdemo.cpp +++ b/cpp/src/pathfindingdemo.cpp @@ -9,9 +9,14 @@ #include "log.hpp" #include "map.hpp" #include "user_input.hpp" +#include "pathfinder.hpp" -PathFindingDemo::PathFindingDemo(int width, int height) : m_Map(width, height) { +PathFindingDemo::PathFindingDemo(int width, int height) : + m_Map(width, height) +{ LOG_DEBUG("."); + // set default pathfinder method + m_PathFinder = pathfinder::create(pathfinder::PathFinderType::LINEAR); } PathFindingDemo::~PathFindingDemo() { LOG_DEBUG("."); } @@ -35,19 +40,21 @@ WorldPos PathFindingDemo::GetRandomPosition() const { std::optional PathFindingDemo::GetMoveTarget() { WorldPos current_player_pos = GetPlayer()->GetPosition(); - if (m_MoveQueue.empty()) { + if (m_Path.empty()) { return {}; } - WorldPos next_player_pos = m_MoveQueue.front(); + WorldPos next_player_pos = m_Path.front(); if (current_player_pos.distance(next_player_pos) > 10.0) { // target not reached yet return next_player_pos; } // target reached, pop it - m_MoveQueue.pop(); - // return nothing - we'll get the next value in the next iteration + //m_MoveQueue.pop(); + m_Path.erase(m_Path.begin()); + // return nothing - if there's next point in the queue, + // we'll get it in the next iteration return {}; } @@ -56,7 +63,7 @@ void PathFindingDemo::UpdatePlayerVelocity() { auto current_pos = player->GetPosition(); double tile_velocity_coeff = m_Map.GetTileVelocityCoeff(current_pos); auto next_pos = GetMoveTarget(); - auto velocity = WorldPos{}; + WorldPos velocity = WorldPos{}; if (next_pos) { velocity = next_pos.value() - current_pos; velocity.normalize(); @@ -73,19 +80,15 @@ void PathFindingDemo::HandleActions(const std::vector &actions) { if (action.type == UserAction::Type::EXIT) { LOG_INFO("Exit requested"); m_ExitRequested = true; - } else if (action.type == UserAction::Type::FIRE) { - LOG_INFO("Fire"); - // AddEntity(m_Player->CreateBomb()); - } else if (action.type == UserAction::Type::MOVE) { - LOG_INFO("Move direction ", action.Argument.position); - m_Player->SetRequestedVelocity(action.Argument.position * 4.0f); - } else if (action.type == UserAction::Type::MOVE_TARGET) { + } else if (action.type == UserAction::Type::SET_MOVE_TARGET) { WorldPos wp = action.Argument.position; - TilePos p = m_Map.WorldToTile(wp); - LOG_INFO("Clearing current move queue and inserting new target: ", wp); - std::queue empty; - std::swap(empty, m_MoveQueue); - m_MoveQueue.push(wp); + LOG_INFO("Calculating path to target: ", wp); + m_Path = m_PathFinder->CalculatePath(wp); + LOG_INFO("Done, path node count: ", m_Path.size()); + } else if (action.type == UserAction::Type::SELECT_PATHFINDER) { + using namespace pathfinder; + PathFinderType type = static_cast(action.Argument.number); + m_PathFinder = create(type); } }; } diff --git a/cpp/src/pathfindingdemo.hpp b/cpp/src/pathfindingdemo.hpp index afa0e77..a716441 100644 --- a/cpp/src/pathfindingdemo.hpp +++ b/cpp/src/pathfindingdemo.hpp @@ -9,6 +9,7 @@ #include "log.hpp" #include "map.hpp" #include "user_input.hpp" +#include "pathfinder.hpp" class PathFindingDemo { public: @@ -34,8 +35,9 @@ public: private: bool m_ExitRequested = false; + Map m_Map; std::vector> m_Entities; std::shared_ptr m_Player; - std::queue m_MoveQueue; - Map m_Map; + pathfinder::Path m_Path; + std::unique_ptr m_PathFinder; }; diff --git a/cpp/src/user_input.cpp b/cpp/src/user_input.cpp index e55a94f..46a6cdb 100644 --- a/cpp/src/user_input.cpp +++ b/cpp/src/user_input.cpp @@ -22,7 +22,6 @@ std::expected UserInput::Init() { return {}; } const std::vector &UserInput::GetActions() { m_Actions.clear(); static WorldPos move_direction = {0.0f, 0.0f}; - static bool send_move_action = false; SDL_Event event; while (SDL_PollEvent(&event)) { @@ -41,34 +40,16 @@ const std::vector &UserInput::GetActions() { m_Actions.emplace_back(UserAction::Type::EXIT); // further processing of inputs is not needed return m_Actions; - case 'w': - case 's': - case 'a': - case 'd': - case SDLK_UP: - case SDLK_DOWN: - case SDLK_LEFT: - case SDLK_RIGHT: { - static std::map move_base{ - {'w', {0.0, 1.0}}, - {'s', {0.0, -1.0}}, - {'a', {1.0, 0.0}}, - {'d', {-1.0, 0.0}}, - {static_cast(SDLK_UP), {0.0, 1.0}}, - {static_cast(SDLK_DOWN), {0.0, -1.0}}, - {static_cast(SDLK_LEFT), {1.0, 0.0}}, - {static_cast(SDLK_RIGHT), {-1.0, 0.0}}, - }; - - float direction = key_down ? -1.0f : 1.0f; - send_move_action = true; - move_direction += move_base[kbd_event.key] * direction; - break; - } - case SDLK_SPACE: - if (key_down) - m_Actions.emplace_back(UserAction::Type::FIRE); - break; + case '1': + case '2': + case '3': + case '4': + if (key_down) { + int selection = kbd_event.key - '0'; + m_Actions.emplace_back(UserAction::Type::SELECT_PATHFINDER, selection); + LOG_INFO("Pathfinder selected: ", selection); + } + break; default: LOG_INFO("Key '", static_cast(kbd_event.key), "' not mapped"); break; @@ -76,16 +57,12 @@ const std::vector &UserInput::GetActions() { } else if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) { SDL_MouseButtonEvent mouse_event = event.button; LOG_DEBUG("Mouse down: ", mouse_event.x, ", ", mouse_event.y); - m_Actions.emplace_back(UserAction::Type::MOVE_TARGET, + m_Actions.emplace_back(UserAction::Type::SET_MOVE_TARGET, WorldPos{mouse_event.x, mouse_event.y}); } else { // TODO uncomment, for now too much noise // LOG_WARNING("Action not processed"); } } - if (send_move_action) { - m_Actions.emplace_back(UserAction::Type::MOVE, move_direction.normalized()); - send_move_action = false; - } return m_Actions; } diff --git a/cpp/src/user_input.hpp b/cpp/src/user_input.hpp index 8a19617..2ea98b5 100644 --- a/cpp/src/user_input.hpp +++ b/cpp/src/user_input.hpp @@ -9,12 +9,13 @@ class UserAction { public: - enum class Type { NONE, EXIT, MOVE, CROUCH, STAND, FIRE, MOVE_TARGET }; + enum class Type { NONE, EXIT, SET_MOVE_TARGET, SELECT_PATHFINDER }; UserAction() = default; UserAction(Type t) : type(t) {} UserAction(Type t, char key) : type(t), Argument{.key = key} {} UserAction(Type t, WorldPos v) : type(t), Argument{.position = v} {} + UserAction(Type t, int arg) : type(t), Argument{.number = arg} {} ~UserAction() = default; Type type; @@ -22,6 +23,7 @@ public: union { WorldPos position; char key; + int number; } Argument; };