]> git.tdb.fi Git - libs/game.git/blobdiff - examples/bassteroids/source/physics.h
Implement a simple physics system in Bassteroids
[libs/game.git] / examples / bassteroids / source / physics.h
diff --git a/examples/bassteroids/source/physics.h b/examples/bassteroids/source/physics.h
new file mode 100644 (file)
index 0000000..a611789
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef PHYSICS_H_
+#define PHYSICS_H_
+
+#include <msp/game/eventobserver.h>
+#include <msp/game/events.h>
+#include <msp/game/handle.h>
+#include <msp/game/system.h>
+#include <msp/geometry/angle.h>
+#include <msp/linal/vector.h>
+
+class PhysicalEntity;
+
+class Physics: public Msp::Game::System
+{
+private:
+       struct SimulatedEntity
+       {
+               Msp::Game::Handle<PhysicalEntity> entity;
+               float inverse_mass = 1.0f;
+               Msp::LinAl::Vector<float, 2> external_force;
+
+               Msp::LinAl::Vector<float, 2> position;
+               Msp::LinAl::Vector<float, 2> velocity;
+
+               unsigned collision_count;
+               Msp::LinAl::Vector<float, 2> position_adjust;
+       };
+
+       struct Collision
+       {
+               std::uint16_t body1 = 0;
+               std::uint16_t body2 = 0;
+               Msp::LinAl::Vector<float, 2> point;
+               float depth = 0.0f;
+               Msp::LinAl::Vector<float, 2> normal;
+       };
+
+       Msp::Game::EventObserver observer;
+       std::vector<SimulatedEntity> entities;
+       unsigned fixture_count = 0;
+       std::vector<Collision> collisions;
+
+public:
+       Physics(Msp::Game::Stage &);
+
+private:
+       void entity_added(const Msp::Game::Events::EntityCreated &);
+
+public:
+       void tick(Msp::Time::TimeDelta) override;
+
+private:
+       template<bool>
+       void copy_in(SimulatedEntity &);
+
+       template<bool>
+       void copy_out(SimulatedEntity &);
+
+       void step(float);
+       void detect_collisions();
+       void solve_collisions();
+       void apply_impulses();
+
+       Collision &get_collision(unsigned, unsigned);
+       void collide_circle_circle(unsigned, unsigned);
+};
+
+#endif