Changeset View
Changeset View
Standalone View
Standalone View
source/simulation2/components/CCmpUnitMotionManager.cpp
- This file was added.
/* Copyright (C) 2020 Wildfire Games. | |||||
* This file is part of 0 A.D. | |||||
* | |||||
* 0 A.D. is free software: you can redistribute it and/or modify | |||||
* it under the terms of the GNU General Public License as published by | |||||
* the Free Software Foundation, either version 2 of the License, or | |||||
* (at your option) any later version. | |||||
* | |||||
* 0 A.D. is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
* GNU General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU General Public License | |||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#include "precompiled.h" | |||||
#include "ICmpUnitMotionManager.h" | |||||
#include "simulation2/MessageTypes.h" | |||||
#include "simulation2/components/ICmpUnitMotion.h" | |||||
#include "simulation2/helpers/Spatial.h" | |||||
#include "simulation2/system/EntityMap.h" | |||||
class CCmpUnitMotionManager : public ICmpUnitMotionManager | |||||
{ | |||||
protected: | |||||
using MotionState = ICmpUnitMotion::MotionState; | |||||
EntityMap<MotionState> m_Units; | |||||
EntityMap<MotionState> m_FormationControllers; | |||||
public: | |||||
static void ClassInit(CComponentManager& componentManager) | |||||
{ | |||||
componentManager.SubscribeToMessageType(MT_Update_MotionUnit); | |||||
componentManager.SubscribeToMessageType(MT_Update_MotionFormation); | |||||
} | |||||
DEFAULT_COMPONENT_ALLOCATOR(UnitMotionManager) | |||||
virtual void Init(const CParamNode& UNUSED(paramNode)) | |||||
{ | |||||
} | |||||
virtual void Deinit() | |||||
{ | |||||
} | |||||
virtual void Serialize(ISerializer& UNUSED(serialize)) | |||||
{ | |||||
} | |||||
virtual void Deserialize(const CParamNode& paramNode, IDeserializer& UNUSED(deserialize)) | |||||
{ | |||||
Init(paramNode); | |||||
} | |||||
virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)) | |||||
{ | |||||
switch (msg.GetType()) | |||||
{ | |||||
case MT_Update_MotionFormation: | |||||
{ | |||||
fixed dt = static_cast<const CMessageUpdate_MotionFormation&> (msg).turnLength; | |||||
MoveFormations(dt); | |||||
break; | |||||
} | |||||
case MT_Update_MotionUnit: | |||||
{ | |||||
fixed dt = static_cast<const CMessageUpdate_MotionUnit&> (msg).turnLength; | |||||
MoveUnits(dt); | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
void Register(entity_id_t ent, bool formationController); | |||||
void Unregister(entity_id_t ent); | |||||
void MoveUnits(fixed dt); | |||||
void MoveFormations(fixed dt); | |||||
void Push(EntityMap<MotionState>::value_type& a, EntityMap<MotionState>::value_type& b); | |||||
}; | |||||
void CCmpUnitMotionManager::Register(entity_id_t ent, bool formationController) | |||||
{ | |||||
MotionState state = { | |||||
CFixedVector2D(), | |||||
CFixedVector2D(), | |||||
CmpPtr<ICmpPosition>(GetSimContext(), ent), | |||||
CmpPtr<ICmpUnitMotion>(GetSimContext(), ent), | |||||
false, | |||||
false | |||||
}; | |||||
if (!formationController) | |||||
m_Units.insert(ent, state); | |||||
else | |||||
m_FormationControllers.insert(ent, state); | |||||
} | |||||
void CCmpUnitMotionManager::Unregister(entity_id_t ent) | |||||
{ | |||||
EntityMap<MotionState>::iterator it = m_Units.find(ent); | |||||
if (it != m_Units.end()) | |||||
{ | |||||
m_Units.erase(it); | |||||
return; | |||||
} | |||||
it = m_FormationControllers.find(ent); | |||||
if (it != m_FormationControllers.end()) | |||||
m_FormationControllers.erase(it); | |||||
} | |||||
void CCmpUnitMotionManager::MoveUnits(fixed dt) | |||||
{ | |||||
std::vector<entity_id_t> drop; | |||||
for (EntityMap<MotionState>::value_type& data : m_Units) | |||||
{ | |||||
// Check that cmpUnitMotion still exists | |||||
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), data.first); | |||||
if (!cmpUnitMotion) | |||||
drop.push_back(data.first); | |||||
else | |||||
{ | |||||
data.second.cmpUnitMotion = cmpUnitMotion; | |||||
data.second.cmpUnitMotion->PreMove(data.second, dt); | |||||
if (!data.second.cmpPosition || !data.second.cmpPosition->IsInWorld()) | |||||
drop.push_back(data.first); | |||||
} | |||||
} | |||||
for (entity_id_t ent : drop) | |||||
Unregister(ent); | |||||
for (EntityMap<MotionState>::value_type& data : m_Units) | |||||
data.second.cmpUnitMotion->Move(data.second, dt); | |||||
for (EntityMap<MotionState>::value_type& data1 : m_Units) | |||||
{ | |||||
if (data1.second.pos == data1.second.initialPos) | |||||
continue; | |||||
for (EntityMap<MotionState>::value_type& data2 : m_Units) | |||||
if (data1.first < data2.first) | |||||
Push(data1, data2); | |||||
} | |||||
for (EntityMap<MotionState>::value_type& data : m_Units) | |||||
data.second.cmpUnitMotion->PostMove(data.second, dt); | |||||
} | |||||
void CCmpUnitMotionManager::MoveFormations(fixed dt) | |||||
{ | |||||
} | |||||
void CCmpUnitMotionManager::Push(EntityMap<MotionState>::value_type& a, EntityMap<MotionState>::value_type& b) | |||||
{ | |||||
CFixedVector2D offset = a.second.pos - b.second.pos; | |||||
if (offset.CompareLength(fixed::FromInt(3))) | |||||
return; | |||||
offset = offset.Multiply(std::max(fixed::Zero(), fixed::FromInt(2) - offset.Length())); | |||||
a.second.pos += offset; | |||||
b.second.pos -= offset; | |||||
} | |||||
REGISTER_COMPONENT_TYPE(UnitMotionManager) |
Wildfire Games · Phabricator