--- /dev/null
+#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