diff --git a/DogTales/dog/dogtales.cpp b/DogTales/dog/dogtales.cpp index 999e06b..7868748 100644 --- a/DogTales/dog/dogtales.cpp +++ b/DogTales/dog/dogtales.cpp @@ -18,11 +18,9 @@ void DogTales::tick() { if (ImGui::BeginTabItem("Player")) { bave::im_text("Controller States"); ImGui::Separator(); - bave::im_text("move_x (Press A/D or Left/Right): {:.2f}", - m_player.get_controller_state("move_x").value()); - bave::im_text("move_y (Press W/S or Up/Down): {:.2f}", - m_player.get_controller_state("move_y").value()); - bave::im_text("Jump (Press 'E'): {:.2f}", m_player.get_controller_state("jump").value()); + bave::im_text("move_x (Press A/D or Left/Right): {:.2f}", m_player.get_controller_state("move_x")); + bave::im_text("move_y (Press W/S or Up/Down): {:.2f}", m_player.get_controller_state("move_y")); + bave::im_text("Jump (Press Space): {:.2f}", m_player.get_controller_state("jump")); ImGui::EndTabItem(); } ImGui::EndTabBar(); diff --git a/DogTales/dog/dogtales.hpp b/DogTales/dog/dogtales.hpp index d627f1f..f7aa509 100644 --- a/DogTales/dog/dogtales.hpp +++ b/DogTales/dog/dogtales.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include +#include namespace dog { class DogTales : public bave::Driver { diff --git a/DogTales/dog/player/PlayerController.cpp b/DogTales/dog/player/PlayerController.cpp deleted file mode 100644 index ac315c0..0000000 --- a/DogTales/dog/player/PlayerController.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "PlayerController.hpp" - -namespace dog { - -PlayerController::PlayerController() { - key_map.insert(std::make_pair("move_x", 0.f)); - key_map.insert(std::make_pair("move_y", 0.f)); - key_map.insert(std::make_pair("jump", 0.f)); -} - -void PlayerController::tick(bave::Seconds dt, bave::App const& app) { - - auto const& key_state = app.get_key_state(); - - bool left = key_state.is_pressed(bave::Key::eA) || key_state.is_pressed(bave::Key::eLeft); - bool right = key_state.is_pressed(bave::Key::eD) || key_state.is_pressed(bave::Key::eRight); - bool up = key_state.is_pressed(bave::Key::eW) || key_state.is_pressed(bave::Key::eUp); - bool down = key_state.is_pressed(bave::Key::eS) || key_state.is_pressed(bave::Key::eDown); - - key_map["move_x"] = 0.f; - key_map["move_x"] = left && !right ? -1.f : key_map["move_x"]; - key_map["move_x"] = right && !left ? 1.f : key_map["move_x"]; - key_map["move_x"] = right && left ? 0.f : key_map["move_x"]; - - key_map["move_y"] = 0.f; - key_map["move_y"] = down && !up ? -1.f : key_map["move_y"]; - key_map["move_y"] = up && !down ? 1.f : key_map["move_y"]; - key_map["move_y"] = up && down ? 0.f : key_map["move_y"]; - - key_map["jump"] = key_state.is_pressed(bave::Key::eW) || key_state.is_pressed(bave::Key::eUp) ? 1.f : 0.f; -} - -std::optional PlayerController::get_controller_state(std::string_view key) const { - if (auto search = key_map.find(key); search != key_map.end()) { - return search->second; - } else { - return -1.f; - } -} - -} // namespace dog diff --git a/DogTales/dog/player/PlayerController.hpp b/DogTales/dog/player/PlayerController.hpp deleted file mode 100644 index e3a9d99..0000000 --- a/DogTales/dog/player/PlayerController.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include -#include -#include - -namespace dog { -class PlayerController { - - public: - PlayerController(); - - void tick(bave::Seconds dt, bave::App const& app); - std::optional get_controller_state(std::string_view key) const; - - private: - std::unordered_map> key_map{}; -}; -} // namespace dog diff --git a/DogTales/dog/player.cpp b/DogTales/dog/player/player.cpp similarity index 70% rename from DogTales/dog/player.cpp rename to DogTales/dog/player/player.cpp index 8308277..3586a9c 100644 --- a/DogTales/dog/player.cpp +++ b/DogTales/dog/player/player.cpp @@ -1,19 +1,24 @@ -#include +#include namespace dog { Player::Player(bave::App& app, glm::vec2 const world_space) : m_app(app), m_world_space(world_space) { m_sprite.set_size(size_v); + + m_player_controller.bind_throttle("move_x", {.lo = bave::Key::eLeft, .hi = bave::Key::eRight}); + m_player_controller.bind_throttle("move_x", {.lo = bave::Key::eA, .hi = bave::Key::eD}); + m_player_controller.bind_throttle("move_y", {.lo = bave::Key::eDown, .hi = bave::Key::eUp}); + m_player_controller.bind_throttle("move_y", {.lo = bave::Key::eS, .hi = bave::Key::eW}); + m_player_controller.bind_trigger("jump", bave::Key::eSpace); } void Player::tick(bave::Seconds const dt) { if (physics_enabled) { m_physics.tick(dt); } - m_player_controller.tick(dt, m_app); auto direction = glm::vec2{}; - direction.x += m_player_controller.get_controller_state("move_x").value(); - direction.y += m_player_controller.get_controller_state("move_y").value(); + direction.x += m_player_controller.get_state("move_x"); + direction.y += m_player_controller.get_state("move_y"); if (direction.x != 0.0f || direction.y != 0.0f) { direction = glm::normalize(direction); @@ -26,9 +31,7 @@ void Player::tick(bave::Seconds const dt) { void Player::draw(bave::Shader& shader) const { m_sprite.draw(shader); } -std::optional Player::get_controller_state(std::string_view key) const { - return m_player_controller.get_controller_state(key); -} +float Player::get_controller_state(std::string_view key) const { return m_player_controller.get_state(key); } void Player::handle_wall_collision() { auto& position = m_physics.position; diff --git a/DogTales/dog/player.hpp b/DogTales/dog/player/player.hpp similarity index 76% rename from DogTales/dog/player.hpp rename to DogTales/dog/player/player.hpp index 9c166b2..344cc34 100644 --- a/DogTales/dog/player.hpp +++ b/DogTales/dog/player/player.hpp @@ -1,8 +1,8 @@ #pragma once #include #include -#include "components/physics.hpp" -#include "player/PlayerController.hpp" +#include +#include namespace dog { class Player { @@ -16,7 +16,7 @@ class Player { bave::Sprite m_sprite{}; component::Physics m_physics{}; - PlayerController m_player_controller{}; + PlayerController m_player_controller{&m_app}; void handle_wall_collision(); @@ -26,7 +26,7 @@ class Player { void tick(bave::Seconds dt); void draw(bave::Shader& shader) const; - std::optional get_controller_state(std::string_view key) const; + float get_controller_state(std::string_view key) const; bool physics_enabled{}; // for debugging }; diff --git a/DogTales/dog/player/player_controller.cpp b/DogTales/dog/player/player_controller.cpp new file mode 100644 index 0000000..429960b --- /dev/null +++ b/DogTales/dog/player/player_controller.cpp @@ -0,0 +1,34 @@ +#include +#include +#include + +namespace dog { + +PlayerController::PlayerController(bave::NotNull app) : m_app(app) {} + +void PlayerController::bind_throttle(std::string_view const key, Throttle const throttle) { + if (throttle.hi == bave::Key::eUnknown) { return; } + auto it = m_mappings.find(key); + if (it == m_mappings.end()) { + auto [i, _] = m_mappings.insert_or_assign(std::string{key}, std::vector{}); + it = i; + } + assert(it != m_mappings.end()); + it->second.push_back(throttle); +} + +float PlayerController::get_state(std::string_view const key) const { + auto const search = m_mappings.find(key); + if (search == m_mappings.end()) { return 0.0f; } + + auto const& mappings = search->second; + auto const is_pressed = [this](bave::Key const key) { return m_app->get_key_state().is_pressed(key); }; + auto ret = 0.0f; + for (auto const& mapping : mappings) { + if (mapping.lo != bave::Key::eUnknown && is_pressed(mapping.lo)) { ret -= 1.0f; } + if (is_pressed(mapping.hi)) { ret += 1.0f; } + } + return std::clamp(ret, -1.0f, 1.0f); +} + +} // namespace dog diff --git a/DogTales/dog/player/player_controller.hpp b/DogTales/dog/player/player_controller.hpp new file mode 100644 index 0000000..4ba4ea9 --- /dev/null +++ b/DogTales/dog/player/player_controller.hpp @@ -0,0 +1,30 @@ +#pragma once +#include +#include +#include +#include + +namespace dog { +class PlayerController { + + public: + struct Throttle { + bave::Key lo{}; + bave::Key hi{}; + }; + + explicit PlayerController(bave::NotNull app); + + void bind_throttle(std::string_view key, Throttle throttle); + void bind_trigger(std::string_view key, bave::Key trigger) { bind_throttle(key, Throttle{.hi = trigger}); } + + float get_state(std::string_view key) const; + + private: + bave::NotNull m_app; + + using Mapping = Throttle; // later to be a variant of KeyMapping / AxisMapping + + std::unordered_map, bave::StringHash, std::equal_to<>> m_mappings{}; +}; +} // namespace dog