1 #include "PathElevatorComponent.h"
2 #include "PhysicsComponent.h"
3 #include "PositionComponent.h"
4
5 #include "../../GameApp/BaseGameApp.h"
6 #include "../../GameApp/BaseGameLogic.h"
7
8 #include "../../Events/EventMgr.h"
9 #include "../../Events/Events.h"
10
11 const char* PathElevatorComponent::g_Name = "PathElevatorComponent";
12
PathElevatorComponent()13 PathElevatorComponent::PathElevatorComponent()
14 :
15 m_CurrentDirection(Direction_None),
16 m_StepTime(0),
17 m_StepElapsedDistance(0.0),
18 m_CurrentStepDefIdx(0),
19 m_pPhysics(nullptr)
20 {
21
22 }
23
VInit(TiXmlElement * pData)24 bool PathElevatorComponent::VInit(TiXmlElement* pData)
25 {
26 assert(pData != NULL);
27
28 m_Properties.LoadFromXml(pData, true);
29
30 assert(m_Properties.speed > DBL_EPSILON);
31 assert(m_Properties.elevatorPath.size() >= 2);
32
33 m_pPhysics = g_pApp->GetGameLogic()->VGetGamePhysics();
34 assert(m_pPhysics != nullptr);
35
36 /*LOG("Speed: " + ToStr(m_Properties.speed));
37 int i = 0;
38 for (auto def : m_Properties.elevatorPath)
39 {
40 if (!def.isWaiting)
41 {
42 LOG("[" + ToStr(i++) + "]: " + ToStr((int)def.direction) + " -> " + ToStr(def.stepDeltaDistance));
43 }
44 else
45 {
46 LOG("[" + ToStr(i++) + "]: " + ToStr(def.isWaiting) + " -> " + ToStr(def.waitMsTime));
47 }
48 }*/
49
50 return true;
51 }
52
VPostInit()53 void PathElevatorComponent::VPostInit()
54 {
55 auto pPC = MakeStrongPtr(m_pOwner->GetComponent<PositionComponent>());
56 assert(pPC != nullptr);
57
58 m_LastPosition = pPC->GetPosition();
59
60 int i = 0;
61 Point previousStepPosition = pPC->GetPosition();
62 for (ElevatorStepDef& elevatorStep : m_Properties.elevatorPath)
63 {
64 //assert(elevatorStep.direction != Direction_None && "PathElevator waiting not supported at the moment");
65 if (elevatorStep.direction != Direction_None)
66 {
67 Point dirSpeed = CalculateSpeed(1.0, elevatorStep.direction);
68 Point deltaStep(dirSpeed.x * elevatorStep.stepDeltaDistance, dirSpeed.y * elevatorStep.stepDeltaDistance);
69
70 elevatorStep.destinationPosition = previousStepPosition + deltaStep;
71
72 previousStepPosition = elevatorStep.destinationPosition;
73 }
74 }
75
76 m_CurrentStepDef = m_Properties.elevatorPath[m_CurrentStepDefIdx];
77
78 // From px/s to m/s
79 m_Properties.speed *= g_pApp->GetGlobalOptions()->platformSpeedModifier;
80
81 m_CurrentSpeed = CalculateSpeed(m_Properties.speed, m_CurrentStepDef.direction);
82 m_pPhysics->VSetLinearSpeed(m_pOwner->GetGUID(), m_CurrentSpeed);
83 }
84
VUpdate(uint32 msDiff)85 void PathElevatorComponent::VUpdate(uint32 msDiff)
86 {
87 if (m_CurrentStepDef.isWaiting)
88 {
89 m_StepTime += msDiff;
90 if (m_StepTime >= m_CurrentStepDef.waitMsTime)
91 {
92 ChangeToNextStep();
93 }
94 }
95 }
96
CalculateSpeed(double speed,Direction dir)97 Point PathElevatorComponent::CalculateSpeed(double speed, Direction dir)
98 {
99 Point calculatedSpeed;
100
101 switch (dir)
102 {
103 case Direction_Up: calculatedSpeed.Set(0, -1.0 * speed); break;
104 case Direction_Up_Right: calculatedSpeed.Set(speed, -1.0 * speed); break;
105 case Direction_Right: calculatedSpeed.Set(speed, 0); break;
106 case Direction_Down_Right: calculatedSpeed.Set(speed, speed); break;
107 case Direction_Down: calculatedSpeed.Set(0, speed); break;
108 case Direction_Down_Left: calculatedSpeed.Set(-1.0 * speed, speed); break;
109 case Direction_Left: calculatedSpeed.Set(-1.0 * speed, 0); break;
110 case Direction_Up_Left: calculatedSpeed.Set(-1.0 * speed, -1.0 * speed); break;
111 case Direction_None: calculatedSpeed.Set(0.0, 0.0); break;
112 default: assert(false);
113 }
114
115 if (dir != Direction_None)
116 {
117 assert(!calculatedSpeed.IsZeroXY());
118 }
119
120 return calculatedSpeed;
121 }
122
ChangeToNextStep()123 void PathElevatorComponent::ChangeToNextStep()
124 {
125 if (m_CurrentStepDefIdx == m_Properties.elevatorPath.size() - 1)
126 {
127 m_CurrentStepDefIdx = 0;
128 }
129 else
130 {
131 m_CurrentStepDefIdx++;
132 }
133
134 m_CurrentStepDef = m_Properties.elevatorPath[m_CurrentStepDefIdx];
135
136 if (m_CurrentStepDef.direction == Direction_None)
137 {
138 m_CurrentSpeed.Set(0.0, 0.0);
139 m_pPhysics->VSetLinearSpeed(m_pOwner->GetGUID(), m_CurrentSpeed);
140 }
141 else
142 {
143 m_CurrentSpeed = CalculateSpeed(m_Properties.speed, m_CurrentStepDef.direction);
144 m_pPhysics->VSetLinearSpeed(m_pOwner->GetGUID(), m_CurrentSpeed);
145 }
146
147 m_StepTime = 0;
148 m_StepElapsedDistance = 0;
149 }
150
ShouldChangeDirection(const Point & newPosition)151 bool PathElevatorComponent::ShouldChangeDirection(const Point& newPosition)
152 {
153 // It should change position if it is past its X destination or Y destination
154 Point speedDirection = CalculateSpeed(1.0f, m_CurrentStepDef.direction);
155
156 // Elevator is moving Up
157 if ((speedDirection.y < (-1.0 * DBL_EPSILON) && (newPosition.y < m_CurrentStepDef.destinationPosition.y)))
158 {
159 return true;
160 }
161 // Elevator is moving Down
162 else if ((speedDirection.y > DBL_EPSILON) && (newPosition.y > m_CurrentStepDef.destinationPosition.y))
163 {
164 return true;
165 }
166 // Elevator is moving Left
167 if ((speedDirection.x < (-1.0 * DBL_EPSILON) && (newPosition.x < m_CurrentStepDef.destinationPosition.x)))
168 {
169 return true;
170 }
171 // Elevator is moving Right
172 else if ((speedDirection.x > DBL_EPSILON) && (newPosition.x > m_CurrentStepDef.destinationPosition.x))
173 {
174 return true;
175 }
176
177 return false;
178 }
179
AddCarriedBody(b2Body * pBody)180 void PathElevatorComponent::AddCarriedBody(b2Body* pBody)
181 {
182 for (auto iter = m_CarriedBodiesList.begin(); iter != m_CarriedBodiesList.end(); ++iter)
183 {
184 if ((*iter) == pBody)
185 {
186 m_CarriedBodiesList.erase(iter);
187 return;
188 }
189 }
190 }
191
RemoveCarriedBody(b2Body * pBody)192 void PathElevatorComponent::RemoveCarriedBody(b2Body* pBody)
193 {
194
195 }
196
OnMoved(Point newPosition)197 void PathElevatorComponent::OnMoved(Point newPosition)
198 {
199 Point positionDelta = Point(newPosition.x - m_LastPosition.x, newPosition.y - m_LastPosition.y);
200
201 m_StepElapsedDistance += max(fabs(positionDelta.x), fabs(positionDelta.y));
202 if (ShouldChangeDirection(newPosition))
203 {
204 ChangeToNextStep();
205 }
206
207 if (m_CarriedBodiesList.empty())
208 {
209 m_LastPosition = newPosition;
210 return;
211 }
212
213 if (fabs(m_CurrentSpeed.x) < DBL_EPSILON)
214 {
215 return;
216 }
217
218
219 std::vector<b2Body*> uniqueCarriedBodies = m_CarriedBodiesList;
220 std::sort(uniqueCarriedBodies.begin(), uniqueCarriedBodies.end());
221 uniqueCarriedBodies.erase(std::unique(uniqueCarriedBodies.begin(), uniqueCarriedBodies.end()), uniqueCarriedBodies.end());
222 for (b2Body* pCarriedBody : uniqueCarriedBodies)
223 {
224 if (pCarriedBody->GetType() == b2_dynamicBody)
225 {
226 Actor* pActor = (Actor*)pCarriedBody->GetUserData();
227 assert(pActor);
228
229 shared_ptr<PhysicsComponent> pPhysicsComponent =
230 MakeStrongPtr(pActor->GetComponent<PhysicsComponent>(PhysicsComponent::g_Name));
231
232 // Provide sanity check
233 if (pPhysicsComponent && pPhysicsComponent->GetNumFootContacts() == 0)
234 {
235 RemoveCarriedBody(pCarriedBody);
236 continue;
237 }
238
239 if (pPhysicsComponent)
240 {
241 pPhysicsComponent->SetExternalSourceSpeed(m_CurrentSpeed);
242 }
243 }
244 }
245
246 m_LastPosition = newPosition;
247 }