Pathfinder WIP
This commit is contained in:
parent
9b08c057e0
commit
ea316ab997
@ -1,14 +1,45 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "math.hpp"
|
#include "math.hpp"
|
||||||
|
#include "map.hpp"
|
||||||
|
|
||||||
namespace pathfinder {
|
namespace pathfinder {
|
||||||
|
|
||||||
using Path = std::vector<TilePos>;
|
using Path = std::vector<WorldPos>;
|
||||||
|
|
||||||
|
enum class PathFinderType {
|
||||||
|
LINEAR = 1,
|
||||||
|
BFS,
|
||||||
|
COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
class PathFinderBase {
|
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> map);
|
||||||
|
virtual Path CalculatePath(WorldPos target) = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Map> m_Map;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
class LinearPathFinder : public PathFinderBase {
|
||||||
|
Path CalculatePath(WorldPos target) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<PathFinderBase> create(PathFinderType type);
|
||||||
|
|
||||||
|
|
||||||
|
} // pathfinder namespace
|
||||||
|
|
||||||
|
@ -9,9 +9,14 @@
|
|||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "map.hpp"
|
#include "map.hpp"
|
||||||
#include "user_input.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(".");
|
LOG_DEBUG(".");
|
||||||
|
// set default pathfinder method
|
||||||
|
m_PathFinder = pathfinder::create(pathfinder::PathFinderType::LINEAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
PathFindingDemo::~PathFindingDemo() { LOG_DEBUG("."); }
|
PathFindingDemo::~PathFindingDemo() { LOG_DEBUG("."); }
|
||||||
@ -35,19 +40,21 @@ WorldPos PathFindingDemo::GetRandomPosition() const {
|
|||||||
std::optional<WorldPos> PathFindingDemo::GetMoveTarget() {
|
std::optional<WorldPos> PathFindingDemo::GetMoveTarget() {
|
||||||
WorldPos current_player_pos = GetPlayer()->GetPosition();
|
WorldPos current_player_pos = GetPlayer()->GetPosition();
|
||||||
|
|
||||||
if (m_MoveQueue.empty()) {
|
if (m_Path.empty()) {
|
||||||
return {};
|
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) {
|
if (current_player_pos.distance(next_player_pos) > 10.0) {
|
||||||
// target not reached yet
|
// target not reached yet
|
||||||
return next_player_pos;
|
return next_player_pos;
|
||||||
}
|
}
|
||||||
// target reached, pop it
|
// target reached, pop it
|
||||||
m_MoveQueue.pop();
|
//m_MoveQueue.pop();
|
||||||
// return nothing - we'll get the next value in the next iteration
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +63,7 @@ void PathFindingDemo::UpdatePlayerVelocity() {
|
|||||||
auto current_pos = player->GetPosition();
|
auto current_pos = player->GetPosition();
|
||||||
double tile_velocity_coeff = m_Map.GetTileVelocityCoeff(current_pos);
|
double tile_velocity_coeff = m_Map.GetTileVelocityCoeff(current_pos);
|
||||||
auto next_pos = GetMoveTarget();
|
auto next_pos = GetMoveTarget();
|
||||||
auto velocity = WorldPos{};
|
WorldPos velocity = WorldPos{};
|
||||||
if (next_pos) {
|
if (next_pos) {
|
||||||
velocity = next_pos.value() - current_pos;
|
velocity = next_pos.value() - current_pos;
|
||||||
velocity.normalize();
|
velocity.normalize();
|
||||||
@ -73,19 +80,15 @@ void PathFindingDemo::HandleActions(const std::vector<UserAction> &actions) {
|
|||||||
if (action.type == UserAction::Type::EXIT) {
|
if (action.type == UserAction::Type::EXIT) {
|
||||||
LOG_INFO("Exit requested");
|
LOG_INFO("Exit requested");
|
||||||
m_ExitRequested = true;
|
m_ExitRequested = true;
|
||||||
} else if (action.type == UserAction::Type::FIRE) {
|
} else if (action.type == UserAction::Type::SET_MOVE_TARGET) {
|
||||||
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) {
|
|
||||||
WorldPos wp = action.Argument.position;
|
WorldPos wp = action.Argument.position;
|
||||||
TilePos p = m_Map.WorldToTile(wp);
|
LOG_INFO("Calculating path to target: ", wp);
|
||||||
LOG_INFO("Clearing current move queue and inserting new target: ", wp);
|
m_Path = m_PathFinder->CalculatePath(wp);
|
||||||
std::queue<WorldPos> empty;
|
LOG_INFO("Done, path node count: ", m_Path.size());
|
||||||
std::swap(empty, m_MoveQueue);
|
} else if (action.type == UserAction::Type::SELECT_PATHFINDER) {
|
||||||
m_MoveQueue.push(wp);
|
using namespace pathfinder;
|
||||||
|
PathFinderType type = static_cast<PathFinderType>(action.Argument.number);
|
||||||
|
m_PathFinder = create(type);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "map.hpp"
|
#include "map.hpp"
|
||||||
#include "user_input.hpp"
|
#include "user_input.hpp"
|
||||||
|
#include "pathfinder.hpp"
|
||||||
|
|
||||||
class PathFindingDemo {
|
class PathFindingDemo {
|
||||||
public:
|
public:
|
||||||
@ -34,8 +35,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_ExitRequested = false;
|
bool m_ExitRequested = false;
|
||||||
|
Map m_Map;
|
||||||
std::vector<std::shared_ptr<Entity>> m_Entities;
|
std::vector<std::shared_ptr<Entity>> m_Entities;
|
||||||
std::shared_ptr<Player> m_Player;
|
std::shared_ptr<Player> m_Player;
|
||||||
std::queue<WorldPos> m_MoveQueue;
|
pathfinder::Path m_Path;
|
||||||
Map m_Map;
|
std::unique_ptr<pathfinder::PathFinderBase> m_PathFinder;
|
||||||
};
|
};
|
||||||
|
@ -22,7 +22,6 @@ std::expected<void, std::string> UserInput::Init() { return {}; }
|
|||||||
const std::vector<UserAction> &UserInput::GetActions() {
|
const std::vector<UserAction> &UserInput::GetActions() {
|
||||||
m_Actions.clear();
|
m_Actions.clear();
|
||||||
static WorldPos move_direction = {0.0f, 0.0f};
|
static WorldPos move_direction = {0.0f, 0.0f};
|
||||||
static bool send_move_action = false;
|
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
|
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
@ -41,33 +40,15 @@ const std::vector<UserAction> &UserInput::GetActions() {
|
|||||||
m_Actions.emplace_back(UserAction::Type::EXIT);
|
m_Actions.emplace_back(UserAction::Type::EXIT);
|
||||||
// further processing of inputs is not needed
|
// further processing of inputs is not needed
|
||||||
return m_Actions;
|
return m_Actions;
|
||||||
case 'w':
|
case '1':
|
||||||
case 's':
|
case '2':
|
||||||
case 'a':
|
case '3':
|
||||||
case 'd':
|
case '4':
|
||||||
case SDLK_UP:
|
if (key_down) {
|
||||||
case SDLK_DOWN:
|
int selection = kbd_event.key - '0';
|
||||||
case SDLK_LEFT:
|
m_Actions.emplace_back(UserAction::Type::SELECT_PATHFINDER, selection);
|
||||||
case SDLK_RIGHT: {
|
LOG_INFO("Pathfinder selected: ", selection);
|
||||||
static std::map<char, WorldPos> move_base{
|
|
||||||
{'w', {0.0, 1.0}},
|
|
||||||
{'s', {0.0, -1.0}},
|
|
||||||
{'a', {1.0, 0.0}},
|
|
||||||
{'d', {-1.0, 0.0}},
|
|
||||||
{static_cast<char>(SDLK_UP), {0.0, 1.0}},
|
|
||||||
{static_cast<char>(SDLK_DOWN), {0.0, -1.0}},
|
|
||||||
{static_cast<char>(SDLK_LEFT), {1.0, 0.0}},
|
|
||||||
{static_cast<char>(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;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_INFO("Key '", static_cast<char>(kbd_event.key), "' not mapped");
|
LOG_INFO("Key '", static_cast<char>(kbd_event.key), "' not mapped");
|
||||||
@ -76,16 +57,12 @@ const std::vector<UserAction> &UserInput::GetActions() {
|
|||||||
} else if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
|
} else if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
|
||||||
SDL_MouseButtonEvent mouse_event = event.button;
|
SDL_MouseButtonEvent mouse_event = event.button;
|
||||||
LOG_DEBUG("Mouse down: ", mouse_event.x, ", ", mouse_event.y);
|
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});
|
WorldPos{mouse_event.x, mouse_event.y});
|
||||||
} else {
|
} else {
|
||||||
// TODO uncomment, for now too much noise
|
// TODO uncomment, for now too much noise
|
||||||
// LOG_WARNING("Action not processed");
|
// 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;
|
return m_Actions;
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,13 @@
|
|||||||
|
|
||||||
class UserAction {
|
class UserAction {
|
||||||
public:
|
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() = default;
|
||||||
UserAction(Type t) : type(t) {}
|
UserAction(Type t) : type(t) {}
|
||||||
UserAction(Type t, char key) : type(t), Argument{.key = key} {}
|
UserAction(Type t, char key) : type(t), Argument{.key = key} {}
|
||||||
UserAction(Type t, WorldPos v) : type(t), Argument{.position = v} {}
|
UserAction(Type t, WorldPos v) : type(t), Argument{.position = v} {}
|
||||||
|
UserAction(Type t, int arg) : type(t), Argument{.number = arg} {}
|
||||||
~UserAction() = default;
|
~UserAction() = default;
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
@ -22,6 +23,7 @@ public:
|
|||||||
union {
|
union {
|
||||||
WorldPos position;
|
WorldPos position;
|
||||||
char key;
|
char key;
|
||||||
|
int number;
|
||||||
} Argument;
|
} Argument;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user