fysxasteroids/engine/ModelBase.cc

411 lines
9.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.;
mPlayerEntityId = NullEntityId;
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
EntityIter 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());
/*
// Update the timers
for (TimerIter timer_iter = mTimers.begin(); timer_iter != mTimers.end(); timer_iter++) {
timer_iter->second.Update(mDeltaSec);
timer_iter++;
}
*/
// simulate the world
mPhysics->Simulate (mDeltaSec, this);
assert (mKilledEntities.size() <= mEntities.size());
// remove killed entities
if (mKilledEntities.size() > 0) {
unsigned int i;
LogDebug ("There are %d entities to kill", mKilledEntities.size());
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 '%u' and type '%u'", id, entity->mType);
if (mEntities.find(id) != mEntities.end ()) {
LogError ("Replacing Entity with id '%u' and type '%u'", id, entity->mType);
}
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);
LogDebug ("Killing entity with id '%u'", id);
if (iter == mEntities.end ()) {
LogError ("Could not kill Entity with id '%u': Entity not found!", id);
return;
} else {
EntityBase *entity = iter->second;
LogDebug ("Entity pointer = 0x%u", entity);
// call the event handler
OnKillEntity (entity);
LogDebug ("Entity pointer (after kill) = 0x%u", 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 ()) {
LogDebug ("iter id=%u entitypointer=0x%x type=%d", iter->first, iter->second, iter->second->mType);
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) {
if (id == NullEntityId)
return NULL;
std::map<unsigned int, EntityBase*>::iterator iter = mEntities.find (id);
if (iter != mEntities.end ()) {
return iter->second;
}
return NULL;
}
EntityBase* ModelBase::GetEntityAt (const vector3d &pos) {
std::map<unsigned int, EntityBase*>::iterator iter = mEntities.begin();
while (iter != mEntities.end ()) {
EntityPhysicState* entity = iter->second->mPhysicState;
/// \todo fix const casting!
vector3d temp_pos (pos);
if ( (temp_pos - entity->GetPosition()).length() < entity->mRadius)
return iter->second;
iter++;
}
return NULL;
}
unsigned int ModelBase::CreateEntityId () {
if (mEntityIdCounter == NullEntityId - 1)
LogError ("Could not create valid entity id, reached maximum value of %u", mEntityIdCounter);
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;
// we alsohave to clear the vector of killed entities!
mKilledEntities.clear();
}
unsigned int ModelBase::GetPlayerEntityId () {
return mPlayerEntityId;
}
void ModelBase::SetPlayerEntityId(unsigned int entity_id) {
mPlayerEntityId = entity_id;
}
/**
* \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 point, 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, point, normal))
return;
reference_entity->CollisionEvent (incidence_entity, point, normal * -1.);
}
/*
* Global functions
*/
unsigned int GetPlayerEntityId () {
if (!ModelInstance) {
LogError ("Couldn't get Player id: Model not initialized!");
}
return ModelInstance->GetPlayerEntityId ();
}
void SetPlayerEntityId(unsigned int entity_id) {
if (!ModelInstance) {
LogError ("Couldn't set Player id: Model not initialized!");
}
ModelInstance->SetPlayerEntityId (entity_id);
}
float GetFrameDuration () {
if (!ModelInstance) {
LogError ("Couldn't get frame duration: Model not initialized!");
}
return ModelInstance->GetFrameDuration ();
}
float GetDurationApplicationStart () {
if (!ModelInstance) {
LogError ("Couldn't get application runtime: Model not initialized!");
}
return ModelInstance->GetDurationApplicationStart ();
}
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);
}
EntityBase* GetEntityAt(const vector3d &pos) {
if (!ModelInstance) {
LogError ("Couldn't execute GetEntityAt(): Model not initialized!");
}
return ModelInstance->GetEntityAt (pos);
}
EntityPhysicState * GetEntityPhysicState (unsigned int id) {
EntityBase *entity = GetEntity (id);
if (entity)
return entity->mPhysicState;
return NULL;
}
/*
void StartTimer(const std::string &id, float sec) {
if (!ModelInstance) {
LogError ("Couldn't execute GetEntity(): Model not initialized!");
}
ModelInstance->StartTimer(id, sec);
}
bool CheckTimer(const std::string &id) {
if (!ModelInstance) {
LogError ("Couldn't execute GetEntity(): Model not initialized!");
}
return ModelInstance->CheckTimer(id);
}
*/
// /** \brief Starts a timer with the given id that expires after sec seconds */
void StartTimer(const std::string &id, float sec) {
if (!ModelInstance) {
LogError ("Couldn't query Timer: Model not initialized!");
}
ModelInstance->StartTimer(id, sec);
}
// /** \brief Checks whether a timer expired */
bool CheckTimer(const std::string &id) {
if (!ModelInstance) {
LogError ("Couldn't query Timer: Model not initialized!");
}
return ModelInstance->CheckTimer(id);
}
// /** \brief Checks whether a timer expired */
float GetTimer(const std::string &id) {
if (!ModelInstance) {
LogError ("Couldn't query Timer: Model not initialized!");
}
return ModelInstance->GetTimer(id);
}
}