From: Mikko Rasa Date: Sun, 20 Nov 2022 13:59:45 +0000 (+0200) Subject: Add infrastructure for receiving player input X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=86c345922f02587d6c49e637535adf5494819652;p=libs%2Fgame.git Add infrastructure for receiving player input --- diff --git a/source/gameview/application.h b/source/gameview/application.h index fbaa47b..5bbc95d 100644 --- a/source/gameview/application.h +++ b/source/gameview/application.h @@ -7,6 +7,7 @@ #include #include #include +#include "playerinput.h" #include "presenter.h" namespace Msp::GameView { @@ -25,6 +26,7 @@ protected: Msp::Game::Director director; GL::WindowView gl_view; Presenter presenter; + PlayerInput player_input; public: Application(); @@ -40,7 +42,8 @@ Application::Application(): gl_device(window), director(resources), gl_view(window), - presenter(director, gl_view) + presenter(director, gl_view), + player_input(director, window) { window.signal_close.connect(sigc::bind(sigc::mem_fun(this, &Application::exit), 0)); } diff --git a/source/gameview/events.h b/source/gameview/events.h new file mode 100644 index 0000000..fcb6395 --- /dev/null +++ b/source/gameview/events.h @@ -0,0 +1,22 @@ +#ifndef MSP_GAMEVIEW_EVENTS_H_ +#define MSP_GAMEVIEW_EVENTS_H_ + +#include + +namespace Msp::GameView { +namespace Events { + +struct PlayerArrived +{ + Input::ControlScheme &controls; +}; + +struct PlayerDeparted +{ + Input::ControlScheme &controls; +}; + +} // namespace Events +} // namespace Msp::GameView + +#endif diff --git a/source/gameview/playerinput.cpp b/source/gameview/playerinput.cpp new file mode 100644 index 0000000..5029ce5 --- /dev/null +++ b/source/gameview/playerinput.cpp @@ -0,0 +1,42 @@ +#include "playerinput.h" +#include + +using namespace std; + +namespace Msp::GameView { + +PlayerInput::PlayerInput(Game::Director &director, Graphics::Window &wnd): + event_source(director.get_event_bus()), + keyboard(wnd), + mouse(wnd) +{ + kbm_hub.attach(keyboard); + kbm_hub.attach(mouse); + + bindings = director.get_resources().get_all(); +} + +void PlayerInput::init_players() +{ + add_player(kbm_hub); +} + +void PlayerInput::add_player(Input::Device &dev) +{ + Player &player = players.emplace_back(&dev, scheme_factory()); + for(Input::Bindings *b: bindings) + if(b->is_compatible(dev)) + { + b->apply_to(*player.controls, dev); + break; + } + event_source.emit(ref(*player.controls)); +} + +void PlayerInput::synthesize_initial_events(Game::EventObserver &observer) +{ + for(const Player &p: players) + event_source.emit_to(observer, ref(*p.controls)); +} + +} // namespace Msp::GameView diff --git a/source/gameview/playerinput.h b/source/gameview/playerinput.h new file mode 100644 index 0000000..16f3c4e --- /dev/null +++ b/source/gameview/playerinput.h @@ -0,0 +1,74 @@ +#ifndef MSP_GAMEVIEW_PLAYERINPUT_H_ +#define MSP_GAMEVIEW_PLAYERINPUT_H_ + +#include +#include +#include +#include +#include +#include +#include +#include "events.h" + +namespace Msp::GameView { + +class PlayerInput: public NonCopyable +{ +public: + using EventSource = Game::EventSource; + + enum Mode + { + ONE_LOCAL_PLAYER, + LOCAL_MULTIPLAYER + }; + +private: + struct Player + { + Input::Device *device = nullptr; + std::unique_ptr controls = nullptr; + }; + + using SchemeFactoryFunc = std::unique_ptr(); + + EventSource event_source; + Input::Keyboard keyboard; + Input::Mouse mouse; + Input::Hub kbm_hub; + std::vector bindings; + SchemeFactoryFunc *scheme_factory = nullptr; + std::vector players; + Mode mode = ONE_LOCAL_PLAYER; + +public: + PlayerInput(Game::Director &, Graphics::Window &); + + template + requires std::is_base_of_v + void set_control_scheme_type(Mode = ONE_LOCAL_PLAYER); + +private: + void init_players(); + void add_player(Input::Device &); + +public: + void synthesize_initial_events(Game::EventObserver &); +}; + + +template + requires std::is_base_of_v +void PlayerInput::set_control_scheme_type(Mode m) +{ + if(scheme_factory) + throw std::logic_error("scheme type already set"); + + mode = m; + scheme_factory = +[]() -> std::unique_ptr { return std::make_unique(); }; + init_players(); +} + +} // namespace Msp::GameView + +#endif diff --git a/source/gameview/resources.cpp b/source/gameview/resources.cpp new file mode 100644 index 0000000..99fbca0 --- /dev/null +++ b/source/gameview/resources.cpp @@ -0,0 +1,11 @@ +#include "resources.h" +#include + +namespace Msp::GameView { + +Resources::Resources() +{ + add_type().suffix(".binds"); +} + +} // namespace Msp::GameView diff --git a/source/gameview/resources.h b/source/gameview/resources.h new file mode 100644 index 0000000..aa20b02 --- /dev/null +++ b/source/gameview/resources.h @@ -0,0 +1,16 @@ +#ifndef MSP_GAMEVIEW_RESOURCES_H_ +#define MSP_GAMEVIEW_RESOURCES_H_ + +#include + +namespace Msp::GameView { + +class Resources: public GL::Resources +{ +public: + Resources(); +}; + +} // namespace Msp::GameView + +#endif