Changeset View
Changeset View
Standalone View
Standalone View
source/simulation2/components/CCmpUnitMotionManager.h
Show All 16 Lines | |||||
#ifndef INCLUDED_CCMPUNITMOTIONMANAGER | #ifndef INCLUDED_CCMPUNITMOTIONMANAGER | ||||
#define INCLUDED_CCMPUNITMOTIONMANAGER | #define INCLUDED_CCMPUNITMOTIONMANAGER | ||||
#include "simulation2/system/Component.h" | #include "simulation2/system/Component.h" | ||||
#include "ICmpUnitMotionManager.h" | #include "ICmpUnitMotionManager.h" | ||||
#include "simulation2/MessageTypes.h" | #include "simulation2/MessageTypes.h" | ||||
#include "simulation2/components/ICmpTerrain.h" | |||||
#include "simulation2/helpers/Grid.h" | |||||
#include "simulation2/system/EntityMap.h" | #include "simulation2/system/EntityMap.h" | ||||
class CCmpUnitMotion; | class CCmpUnitMotion; | ||||
class CCmpUnitMotionManager : public ICmpUnitMotionManager | class CCmpUnitMotionManager : public ICmpUnitMotionManager | ||||
{ | { | ||||
public: | public: | ||||
static void ClassInit(CComponentManager& componentManager) | static void ClassInit(CComponentManager& componentManager) | ||||
{ | { | ||||
componentManager.SubscribeToMessageType(MT_TerrainChanged); | |||||
componentManager.SubscribeToMessageType(MT_TurnStart); | componentManager.SubscribeToMessageType(MT_TurnStart); | ||||
componentManager.SubscribeToMessageType(MT_Update_Final); | componentManager.SubscribeToMessageType(MT_Update_Final); | ||||
componentManager.SubscribeToMessageType(MT_Update_MotionUnit); | componentManager.SubscribeToMessageType(MT_Update_MotionUnit); | ||||
componentManager.SubscribeToMessageType(MT_Update_MotionFormation); | componentManager.SubscribeToMessageType(MT_Update_MotionFormation); | ||||
} | } | ||||
DEFAULT_COMPONENT_ALLOCATOR(UnitMotionManager) | DEFAULT_COMPONENT_ALLOCATOR(UnitMotionManager) | ||||
// Persisted state for each unit. | // Persisted state for each unit. | ||||
struct MotionState | struct MotionState | ||||
{ | { | ||||
// Component references - these must be kept alive for the duration of motion. | // Component references - these must be kept alive for the duration of motion. | ||||
// NB: this is generally not something one should do, but because of the tight coupling here it's doable. | // NB: this is generally not something one should do, but because of the tight coupling here it's doable. | ||||
CmpPtr<ICmpPosition> cmpPosition; | CmpPtr<ICmpPosition> cmpPosition; | ||||
CCmpUnitMotion* cmpUnitMotion; | CCmpUnitMotion* cmpUnitMotion; | ||||
// Position before units start moving | // Position before units start moving | ||||
CFixedVector2D initialPos; | CFixedVector2D initialPos; | ||||
// Transient position during the movement. | // Transient position during the movement. | ||||
CFixedVector2D pos; | CFixedVector2D pos; | ||||
// Accumulated "pushing" from nearby units. | |||||
CFixedVector2D push; | |||||
fixed initialAngle; | fixed initialAngle; | ||||
fixed angle; | fixed angle; | ||||
// If true, the entity needs to be handled during movement. | // If true, the entity needs to be handled during movement. | ||||
bool needUpdate; | bool needUpdate; | ||||
// 'Leak' from UnitMotion. | |||||
bool wentStraight; | bool wentStraight; | ||||
bool wasObstructed; | bool wasObstructed; | ||||
// Marks a unit to be ignored for collisions. | |||||
// This is reset every turn, and is needed because units can otherwise end up inside each other, | |||||
// then being unable to move entirely. | |||||
bool tempIgnore; | |||||
}; | }; | ||||
EntityMap<MotionState> m_Units; | EntityMap<MotionState> m_Units; | ||||
EntityMap<MotionState> m_FormationControllers; | EntityMap<MotionState> m_FormationControllers; | ||||
// Temporary vector, reconstructed each turn (stored here to avoid memory reallocations). | // The vectors are cleared each frame. | ||||
std::vector<EntityMap<MotionState>::iterator> m_MovingUnits; | Grid<std::vector<EntityMap<MotionState>::iterator>> m_MovingUnits; | ||||
bool m_ComputingMotion; | bool m_ComputingMotion; | ||||
static std::string GetSchema() | static std::string GetSchema() | ||||
{ | { | ||||
return "<a:component type='system'/><empty/>"; | return "<a:component type='system'/><empty/>"; | ||||
} | } | ||||
virtual void Init(const CParamNode& UNUSED(paramNode)) | virtual void Init(const CParamNode& UNUSED(paramNode)) | ||||
{ | { | ||||
m_MovingUnits.reserve(40); | |||||
} | } | ||||
virtual void Deinit() | virtual void Deinit() | ||||
{ | { | ||||
} | } | ||||
virtual void Serialize(ISerializer& UNUSED(serialize)) | virtual void Serialize(ISerializer& UNUSED(serialize)) | ||||
{ | { | ||||
} | } | ||||
virtual void Deserialize(const CParamNode& paramNode, IDeserializer& UNUSED(deserialize)) | virtual void Deserialize(const CParamNode& paramNode, IDeserializer& UNUSED(deserialize)) | ||||
{ | { | ||||
Init(paramNode); | Init(paramNode); | ||||
ResetSubdivisions(); | |||||
} | } | ||||
virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)) | virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)) | ||||
{ | { | ||||
switch (msg.GetType()) | switch (msg.GetType()) | ||||
{ | { | ||||
case MT_TerrainChanged: | |||||
{ | |||||
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity()); | |||||
if (cmpTerrain->GetVerticesPerSide() != m_MovingUnits.width()) | |||||
ResetSubdivisions(); | |||||
break; | |||||
} | |||||
case MT_TurnStart: | case MT_TurnStart: | ||||
{ | { | ||||
OnTurnStart(); | OnTurnStart(); | ||||
break; | break; | ||||
} | } | ||||
case MT_Update_MotionFormation: | case MT_Update_MotionFormation: | ||||
{ | { | ||||
fixed dt = static_cast<const CMessageUpdate_MotionFormation&>(msg).turnLength; | fixed dt = static_cast<const CMessageUpdate_MotionFormation&>(msg).turnLength; | ||||
Show All 16 Lines | public: | ||||
virtual void Register(CCmpUnitMotion* component, entity_id_t ent, bool formationController); | virtual void Register(CCmpUnitMotion* component, entity_id_t ent, bool formationController); | ||||
virtual void Unregister(entity_id_t ent); | virtual void Unregister(entity_id_t ent); | ||||
virtual bool ComputingMotion() const | virtual bool ComputingMotion() const | ||||
{ | { | ||||
return m_ComputingMotion; | return m_ComputingMotion; | ||||
} | } | ||||
private: | |||||
void ResetSubdivisions(); | |||||
void OnTurnStart(); | void OnTurnStart(); | ||||
void MoveUnits(fixed dt); | void MoveUnits(fixed dt); | ||||
void MoveFormations(fixed dt); | void MoveFormations(fixed dt); | ||||
void Move(EntityMap<MotionState>& ents, fixed dt); | void Move(EntityMap<MotionState>& ents, fixed dt); | ||||
void Push(EntityMap<MotionState>::value_type& a, EntityMap<MotionState>::value_type& b); | |||||
}; | }; | ||||
void CCmpUnitMotionManager::ResetSubdivisions() | |||||
{ | |||||
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity()); | |||||
if (!cmpTerrain) | |||||
return; | |||||
size_t size = cmpTerrain->GetVerticesPerSide() - 1; | |||||
m_MovingUnits.resize(size * TERRAIN_TILE_SIZE / 20, size * TERRAIN_TILE_SIZE / 20); | |||||
} | |||||
REGISTER_COMPONENT_TYPE(UnitMotionManager) | REGISTER_COMPONENT_TYPE(UnitMotionManager) | ||||
#endif // INCLUDED_CCMPUNITMOTIONMANAGER | #endif // INCLUDED_CCMPUNITMOTIONMANAGER |
Wildfire Games · Phabricator