System(s),
observer(stage.get_event_bus())
{
+ declare_dependency<HitPoints>(UPDATE);
+ declare_dependency<DamageSource>(READ_OLD);
+
observer.observe<Events::Collision>([this](auto &e){ collision(e); });
}
using namespace Msp;
HitPoints::HitPoints(Game::Handle<Game::Entity> e, const Setup &s):
- Component(e),
- setup(s),
- remaining_hits(setup.max_hits)
-{ }
+ BufferedComponent<HitPointsData>(e),
+ setup(s)
+{
+ write().remaining_hits = setup.max_hits;
+}
void HitPoints::take_damage(unsigned amount, unsigned type)
{
if(!(setup.vulnerable_to&(1<<type)))
return;
- remaining_hits = (amount<remaining_hits ? remaining_hits-amount : 0);
+ Data &d = write();
+ d.remaining_hits = (amount<d.remaining_hits ? d.remaining_hits-amount : 0);
}
unsigned vulnerable_to = ~0U;
};
-class HitPoints: public Msp::Game::Component
+struct HitPointsData
+{
+ unsigned remaining_hits;
+};
+
+class HitPoints: public Msp::Game::BufferedComponent<HitPointsData>
{
public:
using Setup = HitPointsSetup;
private:
const Setup &setup;
- unsigned remaining_hits;
public:
HitPoints(Msp::Game::Handle<Msp::Game::Entity>, const Setup &);
void take_damage(unsigned, unsigned);
- bool is_alive() const { return remaining_hits; }
+ bool is_alive() const { return read().remaining_hits; }
};
#endif
event_source(stage.get_event_bus()),
observer(stage.get_event_bus())
{
+ declare_dependency<Game::Transform>(UPDATE);
+ declare_dependency<RigidBody>(UPDATE);
+ declare_dependency<Collider>(READ_OLD);
+
observer.observe<Game::Events::EntityCreated>([this](auto &e){ entity_added(e); });
observer.observe<Game::Events::EntityDestroyed>([this](auto &e){ entity_removed(e); });
bullet_setup{ .physical={ .body={ .mass=0.05f, .moment_of_inertia=0.04f }, .collider={ .type=ColliderType::CIRCLE, .radius=0.2f }},
.hittable={ .damaging=true, .hits={ .max_hits=1 }, .damage={ .amount=1, .type=0 }},
.mesh={ .object_name="Quaver.object" }}
-{ }
+{
+ declare_dependency<Game::Transform>(READ_OLD);
+ declare_dependency<RigidBody>(UPDATE);
+}
void PlayerController::set_controls(Controls *c)
{
using namespace Msp;
RigidBody::RigidBody(Game::Handle<Game::Entity> e, const Setup &s):
- Component(e),
+ BufferedComponent<RigidBodyData>(e),
setup(s)
{ }
void RigidBody::set_velocity(const LinAl::Vector<float, 2> &v)
{
- velocity = v;
+ write().velocity = v;
}
void RigidBody::set_angular_velocity(Geometry::Angle<float> as)
{
- angular_velocity = as;
+ write().angular_velocity = as;
}
void RigidBody::add_force(const LinAl::Vector<float, 2> &f)
{
- force += f;
+ write().force += f;
}
void RigidBody::add_force(const LinAl::Vector<float, 2> &f, const LinAl::Vector<float, 2> &p)
{
- force += f;
+ Data &d = write();
+ d.force += f;
LinAl::Vector<float, 2> r = p-entity->get_transform()->get_position().slice<2>(0);
- torque += r.x*f.y-r.y*f.x;
+ d.torque += r.x*f.y-r.y*f.x;
}
void RigidBody::add_torque(float t)
{
- torque += t;
+ write().torque += t;
}
void RigidBody::clear_forces()
{
- force = LinAl::Vector<float, 2>();
- torque = 0.0f;
+ Data &d = write();
+ d.force = LinAl::Vector<float, 2>();
+ d.torque = 0.0f;
}
float moment_of_inertia = 0.5f;
};
-class RigidBody: public Msp::Game::Component
+struct RigidBodyData
+{
+ Msp::LinAl::Vector<float, 2> velocity;
+ Msp::Geometry::Angle<float> angular_velocity;
+ Msp::LinAl::Vector<float, 2> force;
+ float torque = 0.0f;
+};
+
+class RigidBody: public Msp::Game::BufferedComponent<RigidBodyData>
{
public:
using Setup = RigidBodySetup;
private:
const Setup &setup;
- Msp::LinAl::Vector<float, 2> velocity;
- Msp::Geometry::Angle<float> angular_velocity;
- Msp::LinAl::Vector<float, 2> force;
- float torque = 0.0f;
public:
RigidBody(Msp::Game::Handle<Msp::Game::Entity>, const Setup &);
void add_force(const Msp::LinAl::Vector<float, 2> &, const Msp::LinAl::Vector<float, 2> &);
void add_torque(float);
void clear_forces();
- const Msp::LinAl::Vector<float, 2> &get_velocity() const { return velocity; }
- Msp::Geometry::Angle<float> get_angular_velocity() const { return angular_velocity; }
- const Msp::LinAl::Vector<float, 2> &get_force() const { return force; }
- float get_torque() const { return torque; }
+ const Msp::LinAl::Vector<float, 2> &get_velocity() const { return read().velocity; }
+ Msp::Geometry::Angle<float> get_angular_velocity() const { return read().angular_velocity; }
+ const Msp::LinAl::Vector<float, 2> &get_force() const { return read().force; }
+ float get_torque() const { return read().torque; }
};
#endif
namespace Msp::Game {
Camera::Camera(Handle<Entity> e, const CameraSetup &s):
- Component(e),
- setup(s),
- fov_y(setup.field_of_view_y),
- size(setup.size),
- near_clip(setup.near_clip),
- far_clip(setup.far_clip)
+ BufferedComponent<CameraData>(e),
+ setup(s)
{
- if(!is_orthographic())
- size = { get_aspect(), 1.0f };
+ CameraData &d = write();
+ d.fov_y = setup.field_of_view_y;
+ d.size = setup.size;
+ d.near_clip = setup.near_clip;
+ d.far_clip = setup.far_clip;
+
+ if(!d.is_orthographic())
+ d.size = { d.get_aspect(), 1.0f };
}
void Camera::set_field_of_view(Geometry::Angle<float> f, float a)
{
- if(is_orthographic())
+ Data &d = write();
+ if(d.is_orthographic())
throw logic_error("Camera is not perspective");
- fov_y = f;
- size = { a, 1.0f };
+ d.fov_y = f;
+ d.size = { a, 1.0f };
}
void Camera::set_size(const LinAl::Vector<float, 2> &s)
{
- if(!is_orthographic())
+ Data &d = write();
+ if(!d.is_orthographic())
throw logic_error("Camera is not orthographic");
- size = s;
+ d.size = s;
}
} // namespace Msp::Game
std::string sequence_name;
};
-class Camera: public Component
+struct CameraData
{
-public:
- using Setup = CameraSetup;
-
-private:
- const Setup &setup;
Geometry::Angle<float> fov_y;
LinAl::Vector<float, 2> size;
float height;
float near_clip;
float far_clip;
+ bool is_orthographic() const { return fov_y==Geometry::Angle<float>::zero(); }
+ Geometry::Angle<float> get_fov_horizontal() const { return Geometry::atan(tan(fov_y/2.0f)*get_aspect())*2.0f; }
+ float get_aspect() const { return size.x/size.y; }
+};
+
+class Camera: public BufferedComponent<CameraData>
+{
+public:
+ using Setup = CameraSetup;
+
+private:
+ const Setup &setup;
+
public:
Camera(Handle<Entity>, const Setup &);
void set_field_of_view(Geometry::Angle<float>, float);
void set_size(const LinAl::Vector<float, 2> &);
- bool is_orthographic() const { return fov_y==Geometry::Angle<float>::zero(); }
- Geometry::Angle<float> get_fov_vertical() const { return fov_y; }
- Geometry::Angle<float> get_fov_horizontal() const { return Geometry::atan(tan(fov_y/2.0f)*get_aspect())*2.0f; }
- const LinAl::Vector<float, 2> &get_size() const { return size; }
- float get_aspect() const { return size.x/size.y; }
- float get_near_clip() const { return near_clip; }
- float get_far_clip() const { return far_clip; }
+ bool is_orthographic() const { return read().is_orthographic(); }
+ Geometry::Angle<float> get_fov_vertical() const { return read().fov_y; }
+ Geometry::Angle<float> get_fov_horizontal() const { return read().get_fov_horizontal(); }
+ const LinAl::Vector<float, 2> &get_size() const { return read().size; }
+ float get_aspect() const { return read().get_aspect(); }
+ float get_near_clip() const { return read().near_clip; }
+ float get_far_clip() const { return read().far_clip; }
CameraScaling get_scaling() const { return setup.scaling; }
const std::string &get_sequence_name() const { return setup.sequence_name; }
};
namespace Msp::Game {
Transform::Transform(Handle<Entity> e):
- Component(e)
+ BufferedComponent<TransformData>(e)
{ }
void Transform::set_values(const TransformValues &v)
{
- values = v;
+ write().values = v;
}
void Transform::set_position(const LinAl::Vector<float, 3> &p)
{
- values.position = p;
+ write().values.position = p;
}
void Transform::set_rotation(const Geometry::Quaternion<float> &r)
{
- values.rotation = normalize(r);
+ write().values.rotation = normalize(r);
}
void Transform::set_scale(const LinAl::Vector<float, 3> &s)
{
- values.scale = s;
+ write().values.scale = s;
}
void Transform::update_world_matrix(const Transform *parent)
{
using Affine = Geometry::AffineTransform<float, 3>;
- local_matrix = Affine::translation(values.position)*
- Affine::rotation(values.rotation)*Affine::scaling(values.scale);
+ Data &d = write();
+ d.local_matrix = Affine::translation(d.values.position)*
+ Affine::rotation(d.values.rotation)*Affine::scaling(d.values.scale);
if(parent)
- world_matrix = parent->get_world_matrix()*local_matrix;
+ d.world_matrix = parent->get_world_matrix()*d.local_matrix;
else
- world_matrix = local_matrix;
+ d.world_matrix = d.local_matrix;
}
} // namespace Msp::Game
{ }
};
-class Transform: public Component
+struct TransformData
{
-private:
TransformValues values;
LinAl::Matrix<float, 4, 4> local_matrix = LinAl::Matrix<float, 4, 4>::identity();
LinAl::Matrix<float, 4, 4> world_matrix = LinAl::Matrix<float, 4, 4>::identity();
+};
+class Transform: public BufferedComponent<TransformData>
+{
public:
Transform(Handle<Entity>);
void set_position(const LinAl::Vector<float, 3> &);
void set_rotation(const Geometry::Quaternion<float> &);
void set_scale(const LinAl::Vector<float, 3> &);
- const TransformValues &get_values() const { return values; }
- const LinAl::Vector<float, 3> &get_position() const { return values.position; }
- const Geometry::Quaternion<float> &get_rotation() const { return values.rotation; }
- const LinAl::Vector<float, 3> &get_scale() const { return values.scale; }
- const LinAl::Matrix<float, 4, 4> &get_world_matrix() const { return world_matrix; }
+ const TransformValues &get_values() const { return read().values; }
+ const LinAl::Vector<float, 3> &get_position() const { return read().values.position; }
+ const Geometry::Quaternion<float> &get_rotation() const { return read().values.rotation; }
+ const LinAl::Vector<float, 3> &get_scale() const { return read().values.scale; }
+ const LinAl::Matrix<float, 4, 4> &get_world_matrix() const { return read().world_matrix; }
void update_world_matrix(const Transform *);
};
System(s),
observer(s.get_event_bus())
{
+ declare_dependency<Transform>(CHAINED_UPDATE);
+
observer.observe<Events::EntityCreated>([this](auto &){ transforms_dirty = true; });
observer.observe<Events::EntityDestroyed>([this](auto &){ transforms_dirty = true; });
}
view(v),
event_observer(s.get_event_bus())
{
+ declare_dependency<Game::Transform>(READ_FRESH);
+ declare_dependency<Game::Camera>(READ_FRESH);
+ declare_dependency<MeshRenderer>(WRITE);
+
event_observer.observe<Game::Events::EntityCreated>([this](auto &e){ entity_created(e); });
event_observer.observe<Game::Events::EntityDestroyed>([this](auto &e){ entity_destroyed(e); });
event_observer.observe<Game::Events::CameraChanged>([this](auto &e){ camera_changed(e); });