Hi there,
i am in the phase to adding my 2d physics engine over to my freshly created entity component system and have some design headaches.
It is a simple entity component system, which has "Components" which are just containers and "Systems" which may require n-components and can update or draw a list of entities. There is a component registration which register new component classes (to support unlimited components) who creates new handles and cache this by the class name. Then we have the mighty manager which handles the initialization / update / draw of the systems, keeps a entity list + a list for each system and gets notified when components are added or removed from an entity. An entity is just an component container which do have only the methods for adding/removing and retrieving components. Thats basically it - nothing too fancy and works so far.
But, i have a problem - my current physics engine uses a rigidbody class, which contains all the required properties (like position, velocity, mass, shape etc.) to work with and my entities on the other hand do just contains the "containers" of this properties - some cannot be used (simple types, like numbers, floats) as references which are no references/pointers at all - because its implemented in javascript (numbers are no references).
Is there a good way to integrate a rigidbody/physics engine in a entity component "system"?
My current naiive approach is:
Splitting the rigidbody into multiple components:
- PositionComponent (position vector only)
- VelocityComponent (velocity, angular velocity and both damping factors)
- TransformComponent (rotation angle and transformation matrix)
- MassComponent (mass, inertia and both invert parts of it + density factor)
- ShapeComponent (contains just a reference to actual shape class - like CircleShape which just contains the radius and the massCompute stuff)
- PhysicsComponent (contains all the rest properties from the rigidbody like force, torque, tmp acceleration, next position, friction and restitution coeffs)
Copying code over from my physics engine into the new physics system and change this to use the entity and components like this (seems to be ugly):
PhysicsSystem.prototype.update = function(entities, dt){
var i, entity, posComp, velComp, massComp, phyComp, transComp, gravityComp;
Profiler.begin("Physics step");
// Add forces to dynamic bodies
Profiler.begin("Integrate forces");
var gravityForce = Vec2Pool.get();
for (i = 0; i < entities.size(); i++) {
entity = entities.item(i);
velComp = entity.getComponent(this.velHandle);
massComp = entity.getComponent(this.massHandle);
phyComp = entity.getComponent(this.physicsHandle);
gravityComp = entity.getComponent(this.gravityHandle);
if (!massComp.isStatic() && gravityComp != null) {
math.vec2MultScalar(gravityForce, gravityComp.gravity, massComp.mass);
math.vec2Add(phyComp.force, phyComp.force, gravityForce);
}
}
Profiler.end();
// Integrate velocities
Profiler.begin("Integrate velocity");
for (i = 0; i < entities.size(); i++) {
entity = entities.item(i);
posComp = entity.getComponent(this.posHandle);
velComp = entity.getComponent(this.velHandle);
massComp = entity.getComponent(this.massHandle);
phyComp = entity.getComponent(this.physicsHandle);
if (!massComp.isStatic()) {
this.integrateVelocity(phyComp, massComp, posComp, velComp, dt);
} else {
math.vec2Clone(phyComp.nextPosition, posComp.position);
}
}
Profiler.end();
};
which is orginally this:
PhysicsEngine.prototype.step = function (dt) {
var i, body;
Profiler.begin("Physics step");
// Add gravity force to dynamic bodies
Profiler.begin("Integrate forces");
var gravityForce = Vec2Pool.get();
for (i = 0; i < this.world.size(); i++) {
body = this.world.item(i);
if (!body.isStatic()) {
math.vec2MultScalar(gravityForce, this.world.gravity, body.mass);
body.addForce(gravityForce);
}
}
Profiler.end();
// Integrate velocities
Profiler.begin("Integrate velocity");
for (i = 0; i < this.world.size(); i++) {
body = this.world.item(i);
if (!body.isStatic() && body.awake) {
body.integrateVelocity(dt);
} else {
math.vec2Clone(body.nextPosition, body.position);
}
}
Profiler.end();
...
The only thing which comes to my mind, is to create all the bodies for each entity which references all the properties from the components directly (i could do that because i have an notification system already) - which would force me to change my rigidbody class to use only property types which can be used as references. Other idea is to create a rigidbody component - which justs includes all the properties from all required components (of courses needs also be references as well)
Another things which bugs me is the number of components - is it a good idea to separate the rigidbody properties like this or is it better to use a single component (RigidbodyComponent) which just have all the properties from the original one, but would require that the position component uses the rigidbody position to not need to syncronize positions..... ahhh too much pain ... i have an headache now...