fysxasteroids/engine/ModelBase.h

290 lines
7.6 KiB
C++

#ifndef _MODELBASE_H
#define _MODELBASE_H
#include "Engine.h"
#include "EntityBase.h"
namespace Engine {
class Module;
class PhysicsBase;
class Events;
class EntityFactoryBase;
class OverlayManager;
const unsigned int NullEntityId = std::numeric_limits<unsigned int>::max() - 1;
struct EntityBase;
struct Timer {
Timer() :
mRunning(false),
mCurrentValue(0.)
{}
Timer (float sec_value) :
mRunning(true),
mCurrentValue (sec_value)
{}
Timer (const Timer& timer) :
mRunning (timer.mRunning),
mCurrentValue (timer.mCurrentValue)
{}
Timer& operator= (const Timer& timer) {
if (this != &timer) {
mRunning = timer.mRunning;
mCurrentValue = timer.mCurrentValue;
}
return *this;
}
void Set (float sec_value) {
mCurrentValue = sec_value;
}
float Get () {
return mCurrentValue;
}
bool Query() {
if (mCurrentValue <= 0.)
return true;
return false;
}
void Start() {
mRunning = true;
}
void Pause() {
mRunning = false;
}
bool Update(float sec_value) {
if (mRunning)
mCurrentValue -= sec_value;
return Query();
}
bool mRunning;
float mCurrentValue;
};
/** \brief Represents the current state of the Engine
*
* Represents the State of the Engine and is unaware of anything except itself.
* It manages all Entities, Physics, etc.
*
* It has the following subsystems:
* - Events
* - Physics
* - Variables
*
* \note
* To create an Entity one must call Engine::CreateEntity() which will
* allocate the Entity and performs all the required registrations by calling
* Model::RegisterEntity().
*/
class ModelBase : public Module {
public:
/** Performs simulation, gamelogic, etc */
virtual void Process ();
/** Updates the timer */
void UpdateTimer () {
static float last_frame = 0;
float current_frame = static_cast<float> (SDL_GetTicks ()) * 1.0e-3;
mDurationApplicationStart = current_frame;
mDeltaSec = current_frame - last_frame;
last_frame = current_frame;
UpdateTimers (mDeltaSec);
}
float GetFrameDuration () {
return mDeltaSec;
}
float GetDurationApplicationStart () {
return mDurationApplicationStart;
}
/** Adds the given Entity to the Model */
void RegisterEntity (EntityBase *entity);
/** Removes the Entity with the given id */
void UnregisterEntity (const unsigned int id);
/** Marks an Engine::Entity as killed so that it gets removed after the
* simulation */
void KillEntity (const unsigned int id);
/** Creates an Entity of the given type
*
* This calls the CreateEntity() function on the Model::mEntityFactory to
* create the proper Entity and registers it to the required submodules
* (so far only Model::mPhysics).
*/
EntityBase* CreateEntity (int type);
/** Returns the Entity with the given id */
EntityBase* GetEntity (const unsigned int id);
/** Returns the Entity at the given world coordinates */
EntityBase* GetEntityAt (const vector3d &pos);
EntityBaseIter GetEntityIterBegin () {
return mEntities.begin();
}
EntityBaseIter GetEntityIterEnd() {
return mEntities.end();
}
/** Returns a unused id for an Entity */
unsigned int CreateEntityId ();
/** Removes all Entities */
void ClearEntities ();
/** Returns the id of the entity the player is currently controlling */
unsigned int GetPlayerEntityId ();
/** \brief Assigns the player to an Entity. All controls will be redirected
* \brief to that player
*
* This can be used to disable the controls of of the player by assinging
* the special entity id of NullEntityId */
void SetPlayerEntityId(unsigned int entity_id);
/** Notifies the gamelogic of a collision event */
void SendEntityCollisionEvent (const unsigned int reference_entity_id,
const unsigned int incidence_entity_id, float collision_time,
vector3d point, vector3d normal);
virtual void SetGameState (const unsigned int &state) {
mLastGameState = mGameState;
mGameState = state;
};
unsigned int GetGameState () { return mGameState; };
void StartTimer(const std::string &id, float sec) {
TimerIter cur_timer = mTimers.find(id);
if (cur_timer != mTimers.end()) {
cur_timer->second.Set(sec);
cur_timer->second.Start();
return;
}
mTimers[id] = Timer(sec);
assert (mTimers.size() > 0);
}
bool CheckTimer(const std::string &id) {
TimerIter cur_timer = mTimers.find(id);
if (cur_timer == mTimers.end()) {
return true;
}
return cur_timer->second.Query();
}
float GetTimer (const std::string &id) {
TimerIter cur_timer = mTimers.find(id);
if (cur_timer == mTimers.end()) {
return 0.;
}
return cur_timer->second.Get();
}
void PauseTimers () {
for (TimerIter iter = mTimers.begin(); iter != mTimers.end(); iter++) {
iter->second.Pause();
}
}
void ResumeTimers () {
for (TimerIter iter = mTimers.begin(); iter != mTimers.end(); iter++) {
iter->second.Start();
}
}
void UpdateTimers (float sec) {
TimerIter iter = mTimers.begin();
while (iter != mTimers.end()) {
bool timer_running = iter->second.Update(sec);
if (timer_running) {
LogDebug ("Erasing expired timer %s", iter->first.c_str());
mTimers.erase(iter++);
}
else
++iter;
}
}
protected:
/** \brief Initializes the system */
virtual int OnInit (int argc, char* argv[]);
/** \brief Destroys the system (must be called!) */
virtual void OnDestroy ();
/** \brief Gets called when an entity of the given type is being created */
virtual void OnCreateEntity (const int type, const unsigned int id) {};
/** \brief Gets called when an entity is marked to be killed */
virtual void OnKillEntity (const EntityBase *entity) {};
PhysicsBase *mPhysics;
Events *mEvents;
/** \brief Creates Entities */
EntityFactoryBase *mEntityFactory;
/** \brief contains all Engine::Entities */
std::map<unsigned int, EntityBase *> mEntities;
typedef std::map<unsigned int, EntityBase *>::iterator EntityIter;
/** \brief contains all Engine::Entities that ceased to exist */
std::vector<unsigned int> mKilledEntities;
std::map<std::string, Timer> mTimers;
typedef std::map<std::string, Timer>::iterator TimerIter;
unsigned int mEntityIdCounter;
unsigned int mPlayerEntityId;
unsigned int mGameState;
unsigned int mLastGameState;
float mDeltaSec;
float mDurationApplicationStart;
friend class ViewBase;
friend class OverlayManager;
friend class Engine;
friend class Controller;
};
/** \brief Creates an Entity of the given type and registers at the required modules *
*
* It allocates the memory needed to represent that specific type of Entity.
* At also performs the required registrations at the various Modules.
*
* All Entities that are created with this function get also destroyed in
* Model::Destroy () by calling DestroyEntity () for this Entity.
*
* \note All Entities must be created with this function if you intend to keep
* the different Modules in sync!
*/
EntityBase * CreateEntity (int type);
/** \brief Frees the Memory required by the Entity and unregisters it
*
* This function also frees the memory the Entity is using in its
* different representitions such as EntityVisualState and EntityPhysicState.
*
* It also unregisters the Entity from the different Modules where it was
* registered by CreateEntity.
*/
void DestroyEntity (unsigned int id);
/** \brief Tells the model that the entity is no more existant in the game
* world */
void KillEntity (unsigned int id);
/** \brief Returns the Entity with the given id, NULL otherwise */
EntityBase * GetEntity (unsigned int id);
/** \brief Returns the physical state of the Entity with the given id, NULL otherwise */
EntityPhysicState * GetEntityPhysicState (unsigned int id);
}
#endif // _MODEL_H