]> git.tdb.fi Git - libs/game.git/commitdiff
Implement moving toys with the mouse in the playground example
authorMikko Rasa <tdb@tdb.fi>
Mon, 31 Mar 2025 12:08:46 +0000 (15:08 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 31 Mar 2025 12:35:51 +0000 (15:35 +0300)
examples/playground/data/keyboard_mouse.binds [new file with mode: 0644]
examples/playground/source/controls.cpp [new file with mode: 0644]
examples/playground/source/controls.h [new file with mode: 0644]
examples/playground/source/mousepicker.cpp [new file with mode: 0644]
examples/playground/source/mousepicker.h [new file with mode: 0644]
examples/playground/source/playground.cpp
examples/playground/source/playground.h
examples/playground/source/toy.h

diff --git a/examples/playground/data/keyboard_mouse.binds b/examples/playground/data/keyboard_mouse.binds
new file mode 100644 (file)
index 0000000..338efad
--- /dev/null
@@ -0,0 +1,11 @@
+device KEYBOARD;
+device MOUSE;
+binding "pointer"
+{
+       horizontal { mouse X; };
+       vertical { mouse Y; };
+};
+binding "pick"
+{
+       button { mouse LEFT; };
+};
diff --git a/examples/playground/source/controls.cpp b/examples/playground/source/controls.cpp
new file mode 100644 (file)
index 0000000..2a2c023
--- /dev/null
@@ -0,0 +1,7 @@
+#include "controls.h"
+
+Controls::Controls()
+{
+       add("pointer", pointer);
+       add("pick", pick);
+}
diff --git a/examples/playground/source/controls.h b/examples/playground/source/controls.h
new file mode 100644 (file)
index 0000000..2f3db15
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef CONTROLS_H_
+#define CONTROLS_H_
+
+#include <msp/input/control.h>
+#include <msp/input/controlscheme.h>
+
+struct Controls: public Msp::Input::ControlScheme
+{
+       Msp::Input::PlanarControl pointer;
+       Msp::Input::BinaryControl pick;
+
+       Controls();
+};
+
+#endif
diff --git a/examples/playground/source/mousepicker.cpp b/examples/playground/source/mousepicker.cpp
new file mode 100644 (file)
index 0000000..77fe378
--- /dev/null
@@ -0,0 +1,69 @@
+#include "mousepicker.h"
+#include <msp/game/camera.h>
+#include <msp/game/entity.h>
+#include <msp/game/transform.h>
+#include "controls.h"
+#include "toy.h"
+
+using namespace std;
+using namespace Msp;
+
+MousePicker::MousePicker(Game::Stage &s, Game::PhysicsSystem &p):
+       System(s),
+       physics(p)
+{
+       declare_dependency<Game::Transform>(UPDATE);
+       declare_dependency<Game::Camera>(READ_OLD);
+       declare_dependency<Game::RigidBody>(WRITE);
+}
+
+void MousePicker::set_controls(Controls *c)
+{
+       controls = c;
+}
+
+void MousePicker::tick(Time::TimeDelta)
+{
+       if(!controls)
+               return;
+
+       Game::Handle<Game::Camera> camera = stage.get_active_camera();
+       if(!camera)
+               return;
+
+       const Geometry::AffineTransform<float, 3> &cam_world_tf = camera->get_entity()->get_transform()->get_world_transform();
+       Geometry::Ray<float, 3> ray = camera->create_ray(controls->pointer.get_value());
+       ray = cam_world_tf.transform(ray);
+
+       if(controls->pick.was_activated())
+       {
+               Game::RaycastHit hit = physics.cast_ray(ray);
+               if(hit)
+               {
+                       drag_origin = hit.position;
+                       drag_normal = normalize(compose(cam_world_tf.transform(LinAl::Vector<float, 3>(0.0f, 0.0f, 1.0f)).slice<2>(0), 0.0f));
+                       Game::Handle<Toy> toy = dynamic_handle_cast<Toy>(hit.shape->get_entity());
+                       if(toy)
+                       {
+                               held_toy = toy;
+                               hold_offset = hit.position-toy->get_transform()->get_position();
+                               held_toy->get_rigid_body()->set_kinematic(true);
+                       }
+               }
+       }
+       else if(held_toy)
+       {
+               if(controls->pick.was_released())
+               {
+                       held_toy->get_rigid_body()->set_kinematic(false);
+                       held_toy = nullptr;
+               }
+               else
+               {
+                       float d = dot(drag_origin-ray.get_start(), drag_normal)/dot(ray.get_direction(), drag_normal);
+                       held_toy->get_transform()->set_position(ray.get_start()+ray.get_direction()*d-hold_offset);
+               }
+       }
+
+       controls->reset_edges();
+}
diff --git a/examples/playground/source/mousepicker.h b/examples/playground/source/mousepicker.h
new file mode 100644 (file)
index 0000000..bfaf304
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef MOUSEPICKER_H_
+#define MOUSEPICKER_H_
+
+#include <msp/game/physicssystem.h>
+#include <msp/game/system.h>
+#include <msp/gameview/events.h>
+#include <msp/linal/vector.h>
+
+struct Controls;
+class Toy;
+
+class MousePicker: public Msp::Game::System
+{
+private:
+       Msp::Game::PhysicsSystem &physics;
+       Controls *controls = nullptr;
+       Msp::Game::Handle<Toy> held_toy;
+       Msp::LinAl::Vector<float, 3> hold_offset;
+       Msp::LinAl::Vector<float, 3> drag_origin;
+       Msp::LinAl::Vector<float, 3> drag_normal;
+
+public:
+       MousePicker(Msp::Game::Stage &, Msp::Game::PhysicsSystem &);
+
+       void set_controls(Controls *);
+
+       void tick(Msp::Time::TimeDelta) override;
+};
+
+#endif
index 0db8e32c7747f1edd3c17682b80bd1d189709a86..53551292ca473debc08a211f7d5c4818fcfcbb31 100644 (file)
@@ -3,7 +3,9 @@
 #include <msp/game/physicssystem.h>
 #include <msp/game/root.h>
 #include <msp/game/stageplan.h>
+#include "controls.h"
 #include "fixture.h"
+#include "mousepicker.h"
 #include "playground/setups.h"
 #include "toy.h"
 
@@ -11,6 +13,7 @@ using namespace std;
 using namespace Msp;
 
 Playground::Playground(int, char **):
+       event_observer(director.get_event_bus()),
        stage(director.create_stage("playground")),
        cam_entity(stage.get_root(), Game::TransformValues({ 0.0f, -1.5f, 1.5f }, Geometry::make_quat(45.0f*Geometry::degrees, { 1.0f, 0.0f, 0.0f }))),
        camera(cam_entity, resources.get<Game::CameraSetup>("playground.camera.setup")),
@@ -21,7 +24,10 @@ Playground::Playground(int, char **):
 {
        Game::StagePlan::register_entity_type<Fixture>("fixture");
 
-       stage.add_system<Game::PhysicsSystem>();
+       event_observer.observe<GameView::Events::LocalPlayerArrived>([this](auto &e){ player_arrived(e); });
+
+       Game::PhysicsSystem &physics = stage.add_system<Game::PhysicsSystem>();
+       mouse_picker = &stage.add_system<MousePicker>(physics);
        stage.apply_plan(resources.get<Game::StagePlan>("playground.stage"));
 
        vector<ToySetup *> toy_setups = resources.get_all<ToySetup>();
@@ -36,9 +42,16 @@ Playground::Playground(int, char **):
                toys.emplace_back(stage.get_root(), setup, Game::TransformValues(pos, Geometry::Quaternion<float>::one()));
        }
 
+       player_input.set_control_scheme_type<Controls>();
+
        director.activate_stage(stage);
 }
 
+void Playground::player_arrived(const GameView::Events::LocalPlayerArrived &e)
+{
+       mouse_picker->set_controls(dynamic_cast<Controls *>(&e.controls));
+}
+
 
 PlaygroundResources::PlaygroundResources()
 {
index 01d48b3265cfa2babf44977299a89850f1aa87f7..b07622b32661bb88a62190c958b949765f6d63c3 100644 (file)
@@ -10,6 +10,7 @@
 #include <msp/gameview/application.h>
 #include <msp/gameview/resources.h>
 
+class MousePicker;
 class Toy;
 
 class PlaygroundResources: public Msp::Game::ApplicationResources, public Msp::GameView::Resources
@@ -21,7 +22,9 @@ public:
 class Playground: public Msp::GameView::Application<Playground, PlaygroundResources>
 {
 private:
+       Msp::Game::EventObserver event_observer;
        Msp::Game::Stage &stage;
+       MousePicker *mouse_picker = nullptr;
        Msp::Game::Owned<Msp::Game::Entity> cam_entity;
        Msp::Game::Owned<Msp::Game::Camera> camera;
        Msp::Game::ShadowTargetSetup shadow_setup;
@@ -32,6 +35,9 @@ private:
 
 public:
        Playground(int, char **);
+
+private:
+       void player_arrived(const Msp::GameView::Events::LocalPlayerArrived &);
 };
 
 #endif
index 2a24e3a704a6b518762467e6da45430bb4007b54..4a7558b64c43ae7e067276b979ccc8316536699e 100644 (file)
@@ -20,6 +20,8 @@ private:
 
 public:
        Toy(Msp::Game::Handle<Msp::Game::Entity>, const Setup &, const Msp::Game::TransformValues &);
+
+       Msp::Game::Handle<Msp::Game::RigidBody> get_rigid_body() { return rigid_body; }
 };
 
 #endif