]> git.tdb.fi Git - libs/game.git/commitdiff
Add infrastructure for receiving player input
authorMikko Rasa <tdb@tdb.fi>
Sun, 20 Nov 2022 13:59:45 +0000 (15:59 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sun, 20 Nov 2022 13:59:45 +0000 (15:59 +0200)
source/gameview/application.h
source/gameview/events.h [new file with mode: 0644]
source/gameview/playerinput.cpp [new file with mode: 0644]
source/gameview/playerinput.h [new file with mode: 0644]
source/gameview/resources.cpp [new file with mode: 0644]
source/gameview/resources.h [new file with mode: 0644]

index fbaa47b41bbfb72adb84e50889ff66e7d3f62531..5bbc95dee538a5931f4fed7e9e00b7fd346f7c6d 100644 (file)
@@ -7,6 +7,7 @@
 #include <msp/gl/windowview.h>
 #include <msp/graphics/display.h>
 #include <msp/graphics/window.h>
+#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<T, R>::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 (file)
index 0000000..fcb6395
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef MSP_GAMEVIEW_EVENTS_H_
+#define MSP_GAMEVIEW_EVENTS_H_
+
+#include <msp/input/controlscheme.h>
+
+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 (file)
index 0000000..5029ce5
--- /dev/null
@@ -0,0 +1,42 @@
+#include "playerinput.h"
+#include <msp/input/bindings.h>
+
+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<Input::Bindings>();
+}
+
+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<Events::PlayerArrived>(ref(*player.controls));
+}
+
+void PlayerInput::synthesize_initial_events(Game::EventObserver &observer)
+{
+       for(const Player &p: players)
+               event_source.emit_to<Events::PlayerArrived>(observer, ref(*p.controls));
+}
+
+} // namespace Msp::GameView
diff --git a/source/gameview/playerinput.h b/source/gameview/playerinput.h
new file mode 100644 (file)
index 0000000..16f3c4e
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef MSP_GAMEVIEW_PLAYERINPUT_H_
+#define MSP_GAMEVIEW_PLAYERINPUT_H_
+
+#include <memory>
+#include <msp/input/bindings.h>
+#include <msp/input/controlscheme.h>
+#include <msp/input/hub.h>
+#include <msp/input/keyboard.h>
+#include <msp/input/mouse.h>
+#include <msp/game/director.h>
+#include "events.h"
+
+namespace Msp::GameView {
+
+class PlayerInput: public NonCopyable
+{
+public:
+       using EventSource = Game::EventSource<Events::PlayerArrived, Events::PlayerDeparted>;
+
+       enum Mode
+       {
+               ONE_LOCAL_PLAYER,
+               LOCAL_MULTIPLAYER
+       };
+
+private:
+       struct Player
+       {
+               Input::Device *device = nullptr;
+               std::unique_ptr<Input::ControlScheme> controls = nullptr;
+       };
+
+       using SchemeFactoryFunc = std::unique_ptr<Input::ControlScheme>();
+
+       EventSource event_source;
+       Input::Keyboard keyboard;
+       Input::Mouse mouse;
+       Input::Hub kbm_hub;
+       std::vector<Input::Bindings *> bindings;
+       SchemeFactoryFunc *scheme_factory = nullptr;
+       std::vector<Player> players;
+       Mode mode = ONE_LOCAL_PLAYER;
+
+public:
+       PlayerInput(Game::Director &, Graphics::Window &);
+
+       template<typename T>
+               requires std::is_base_of_v<Input::ControlScheme, T>
+       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<typename T>
+       requires std::is_base_of_v<Input::ControlScheme, T>
+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<Input::ControlScheme> { return std::make_unique<T>(); };
+       init_players();
+}
+
+} // namespace Msp::GameView
+
+#endif
diff --git a/source/gameview/resources.cpp b/source/gameview/resources.cpp
new file mode 100644 (file)
index 0000000..99fbca0
--- /dev/null
@@ -0,0 +1,11 @@
+#include "resources.h"
+#include <msp/input/bindings.h>
+
+namespace Msp::GameView {
+
+Resources::Resources()
+{
+       add_type<Input::Bindings>().suffix(".binds");
+}
+
+} // namespace Msp::GameView
diff --git a/source/gameview/resources.h b/source/gameview/resources.h
new file mode 100644 (file)
index 0000000..aa20b02
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef MSP_GAMEVIEW_RESOURCES_H_
+#define MSP_GAMEVIEW_RESOURCES_H_
+
+#include <msp/gl/resources.h>
+
+namespace Msp::GameView {
+
+class Resources: public GL::Resources
+{
+public:
+       Resources();
+};
+
+} // namespace Msp::GameView
+
+#endif