fysxasteroids/engine/ModelBase.cc

291 lines
6.8 KiB
C++

#include "ModelBase.h"
#include "PhysicsBase.h"
#include "EntityBase.h"
#include "EntityFactoryBase.h"
#include <coll2d.h>
#include <assert.h>
namespace Engine {
static ModelBase* ModelInstance = NULL;
/*
* Inherited Module functions
*/
int ModelBase::OnInit (int argc, char* argv[]) {
LogDebug ("Model Init");
ModelInstance = this;
mKilledEntities.clear ();
mEntityIdCounter = 0;
mDeltaSec = 0.;
return 0;
}
void ModelBase::OnDestroy () {
LogDebug ("Model Destroy");
std::map<unsigned int, EntityBase*>::iterator iter = mEntities.begin ();
std::map<unsigned int, EntityBase*>::iterator next = iter;
// Since DestroyEntity () also erases the entry in mEntities iter gets
// invalid. Therefore we have to store the iterator that follows iter
while (iter != mEntities.end ()) {
next = iter;
next ++;
DestroyEntity (iter->first);
iter = next;
}
ModelInstance = NULL;
}
/*
* Model specific functions
*/
void ModelBase::Process () {
// Process the controllers and state of all entities
std::map<unsigned int, EntityBase*>::iterator entity_iter = mEntities.begin();
do {
if (entity_iter->second == NULL) {
LogError ("Entity with id %d does not exist!", entity_iter->first);
}
entity_iter->second->Update(mDeltaSec);
entity_iter++;
} while (entity_iter != mEntities.end());
// simulate the world
mPhysics->Simulate (mDeltaSec, this);
// remove killed entities
unsigned int i;
for (i = 0; i < mKilledEntities.size(); i++)
UnregisterEntity (mKilledEntities[i]);
mKilledEntities.clear();
}
EntityBase* ModelBase::CreateEntity (int type) {
// Create a new entity id
unsigned int entity_id = CreateEntityId();
// Call the event
OnCreateEntity (type, entity_id);
// Create the entity
EntityBase* result = mEntityFactory->CreateEntity (type);
result->SetId (entity_id);
// And register it
RegisterEntity (result);
return result;
}
void ModelBase::RegisterEntity (EntityBase* entity) {
unsigned int id = entity->mId;
LogDebug ("Registering Entity with id '%d'", id);
if (mEntities.find(id) != mEntities.end ()) {
LogError ("Replacing Entity with id '%d'", id);
}
if (entity->mPhysicState)
mPhysics->RegisterEntity (entity->mPhysicState);
mEntities[id] = entity;
}
void ModelBase::KillEntity (const unsigned int id) {
std::map<unsigned int, EntityBase*>::iterator iter = mEntities.find (id);
if (iter == mEntities.end ()) {
LogError ("Could not kill Entity with id '%d': Entity not found!", id);
return;
} else {
EntityBase *entity = iter->second;
// call the event handler
OnKillEntity (entity);
if (entity->mPhysicState) {
entity->mPhysicState->mAlive = false;
}
mKilledEntities.push_back (iter->first);
}
}
void ModelBase::UnregisterEntity (const unsigned int id) {
std::map<unsigned int, EntityBase*>::iterator iter = mEntities.find (id);
if (iter == mEntities.end ()) {
LogError ("Could not unregister Entity with id '%d': Entity not found!", id);
return;
} else {
EntityBase *entity = iter->second;
if (entity->mPhysicState) {
mPhysics->UnregisterEntity (id);
entity->mPhysicState = NULL;
}
if (entity->mControllerState) {
delete entity->mControllerState;
entity->mControllerState = NULL;
}
delete entity;
mEntities.erase (iter);
}
}
EntityBase* ModelBase::GetEntity (const unsigned int id) {
std::map<unsigned int, EntityBase*>::iterator iter = mEntities.find (id);
if (iter != mEntities.end ()) {
return iter->second;
}
return NULL;
}
unsigned int ModelBase::CreateEntityId () {
return ++mEntityIdCounter;
}
void ModelBase::ClearEntities () {
LogDebug ("Clearing all %d entities.", mEntities.size());
std::map<unsigned int, EntityBase*>::iterator iter = mEntities.begin ();
std::map<unsigned int, EntityBase*>::iterator next = iter;
// Since DestroyEntity () also erases the entry in mEntities iter gets
// invalid. Therefore we have to store the iterator that follows iter
while (iter != mEntities.end ()) {
next = iter;
next ++;
DestroyEntity (iter->first);
iter = next;
}
mEntityIdCounter = 0;
}
unsigned int ModelBase::GetPlayerEntityId () {
return mPlayerEntityId;
}
/**
* \param collision_time The time when the collision occured relative to the start of the simulation frame
*/
void ModelBase::SendEntityCollisionEvent (const unsigned int reference_entity_id,
const unsigned int incidence_entity_id, float collision_time, vector3d normal) {
// Check whether we report the same contact over and over
static unsigned int last_reference_entity_id = 0;
static unsigned int last_incidence_entity_id = 0;
static float last_collision_time = -1.;
if (!reference_entity_id || !incidence_entity_id)
return;
if (last_reference_entity_id != 0) {
if (last_reference_entity_id == reference_entity_id
&& last_incidence_entity_id == incidence_entity_id
&& last_collision_time == collision_time) {
return;
}
}
// update the last_* entries
last_reference_entity_id = reference_entity_id;
last_incidence_entity_id = incidence_entity_id;
last_collision_time = collision_time;
// now we need to get the Entities and check whether we should
// call EntityBase::CollisionEvent()
EntityBase* reference_entity = GetEntity (reference_entity_id);
EntityBase* incidence_entity = GetEntity (incidence_entity_id);
LogDebug ("Received collision type ref = %d type inc = %d",
reference_entity->mType,
incidence_entity->mType);
// If the incidence entity accepted the collision we can return, otherwise
// we perform the symmetric collision event.
if (incidence_entity->CollisionEvent (reference_entity))
return;
reference_entity->CollisionEvent (incidence_entity);
}
/*
* Global functions
*/
unsigned int GetPlayerEntityId () {
if (!ModelInstance) {
LogError ("Couldn't create Entity: Model not initialized!");
}
return ModelInstance->GetPlayerEntityId ();
}
float GetFrameDuration () {
if (!ModelInstance) {
LogError ("Couldn't create Entity: Model not initialized!");
}
return ModelInstance->GetFrameDuration ();
}
EntityBase * CreateEntity (int type) {
if (!ModelInstance) {
LogError ("Couldn't create Entity: Model not initialized!");
}
EntityBase *result = ModelInstance->CreateEntity (type);
return result;
}
void DestroyEntity (unsigned int id) {
if (!ModelInstance) {
LogError ("Couldn't destroy Entity: Model not initialized!");
}
ModelInstance->UnregisterEntity (id);
}
void KillEntity (unsigned int id) {
if (!ModelInstance) {
LogError ("Couldn't kill Entity: Model not initialized!");
}
ModelInstance->KillEntity (id);
}
EntityBase * GetEntity (unsigned int id) {
if (!ModelInstance) {
LogError ("Couldn't execute GetEntity(): Model not initialized!");
}
return ModelInstance->GetEntity (id);
}
EntityPhysicState * GetEntityPhysicState (unsigned int id) {
EntityBase *entity = GetEntity (id);
if (entity)
return entity->mPhysicState;
return NULL;
}
}