summary refs log tree commit diff stats
path: root/src/systems/pondering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/systems/pondering.cpp')
-rw-r--r--src/systems/pondering.cpp268
1 files changed, 268 insertions, 0 deletions
diff --git a/src/systems/pondering.cpp b/src/systems/pondering.cpp new file mode 100644 index 0000000..4a165b1 --- /dev/null +++ b/src/systems/pondering.cpp
@@ -0,0 +1,268 @@
1#include "pondering.h"
2#include "game.h"
3#include "components/ponderable.h"
4#include "components/transformable.h"
5#include "components/orientable.h"
6#include "components/mappable.h"
7#include "systems/orienting.h"
8#include "consts.h"
9
10void PonderingSystem::tick(double dt)
11{
12 auto entities = game_.getEntityManager().getEntitiesWithComponents<
13 PonderableComponent,
14 TransformableComponent>();
15
16 auto maps = game_.getEntityManager().getEntitiesWithComponents<
17 MappableComponent>();
18
19 for (id_type entity : entities)
20 {
21 auto& transformable = game_.getEntityManager().
22 getComponent<TransformableComponent>(entity);
23
24 auto& ponderable = game_.getEntityManager().
25 getComponent<PonderableComponent>(entity);
26
27 // Accelerate
28 ponderable.setVelocityX(
29 ponderable.getVelocityX() + ponderable.getAccelX() * dt);
30
31 ponderable.setVelocityY(
32 ponderable.getVelocityY() + ponderable.getAccelY() * dt);
33
34 const double oldX = transformable.getX();
35 const double oldY = transformable.getY();
36 const double oldRight = oldX + transformable.getW();
37 const double oldBottom = oldY + transformable.getH();
38
39 double newX = oldX + ponderable.getVelocityX() * dt;
40 double newY = oldY + ponderable.getVelocityY() * dt;
41
42 bool oldGrounded = ponderable.isGrounded();
43 ponderable.setGrounded(false);
44
45 for (id_type mapEntity : maps)
46 {
47 auto& mappable = game_.getEntityManager().
48 getComponent<MappableComponent>(mapEntity);
49
50 if (newX < oldX)
51 {
52 for (auto it = mappable.getLeftBoundaries().lower_bound(oldX);
53 (it != std::end(mappable.getLeftBoundaries())) && (it->first >= newX);
54 it++)
55 {
56 if ((oldBottom > it->second.getLower())
57 && (oldY < it->second.getUpper()))
58 {
59 // We have a collision!
60 processCollision(
61 entity,
62 Direction::left,
63 newX,
64 newY,
65 it->first,
66 it->second.getType());
67 }
68 }
69 } else if (newX > oldX)
70 {
71 for (auto it = mappable.getRightBoundaries().lower_bound(oldRight);
72 (it != std::end(mappable.getRightBoundaries()))
73 && (it->first <= (newX + transformable.getW()));
74 it++)
75 {
76 if ((oldBottom > it->second.getLower())
77 && (oldY < it->second.getUpper()))
78 {
79 // We have a collision!
80 processCollision(
81 entity,
82 Direction::right,
83 newX,
84 newY,
85 it->first,
86 it->second.getType());
87 }
88 }
89 }
90
91 if (newY < oldY)
92 {
93 for (auto it = mappable.getUpBoundaries().lower_bound(oldY);
94 (it != std::end(mappable.getUpBoundaries())) && (it->first >= newY);
95 it++)
96 {
97 if ((oldRight > it->second.getLower())
98 && (oldX < it->second.getUpper()))
99 {
100 // We have a collision!
101 processCollision(
102 entity,
103 Direction::up,
104 newX,
105 newY,
106 it->first,
107 it->second.getType());
108 }
109 }
110 } else if (newY > oldY)
111 {
112 for (auto it = mappable.getDownBoundaries().lower_bound(oldBottom);
113 (it != std::end(mappable.getDownBoundaries()))
114 && (it->first <= (newY + transformable.getH()));
115 it++)
116 {
117 if ((oldRight > it->second.getLower())
118 && (oldX < it->second.getUpper()))
119 {
120 // We have a collision!
121 processCollision(
122 entity,
123 Direction::down,
124 newX,
125 newY,
126 it->first,
127 it->second.getType());
128 }
129 }
130 }
131 }
132
133 // Move
134 transformable.setX(newX);
135 transformable.setY(newY);
136
137 // Perform cleanup for orientable entites
138 if (game_.getEntityManager().hasComponent<OrientableComponent>(entity))
139 {
140 auto& orientable = game_.getEntityManager().
141 getComponent<OrientableComponent>(entity);
142
143 // Handle changes in groundedness
144 if (ponderable.isGrounded() != oldGrounded)
145 {
146 if (ponderable.isGrounded())
147 {
148 game_.getSystemManager().getSystem<OrientingSystem>().land(entity);
149 } else {
150 game_.getSystemManager().
151 getSystem<OrientingSystem>().startFalling(entity);
152 }
153 }
154
155 // Complete dropping, if necessary
156 if (orientable.getDropState() == OrientableComponent::DropState::active)
157 {
158 orientable.setDropState(OrientableComponent::DropState::none);
159 }
160 }
161 }
162}
163
164void PonderingSystem::initializeBody(
165 id_type entity,
166 PonderableComponent::Type type)
167{
168 auto& ponderable = game_.getEntityManager().
169 emplaceComponent<PonderableComponent>(entity, type);
170
171 if (type == PonderableComponent::Type::freefalling)
172 {
173 ponderable.setAccelY(NORMAL_GRAVITY);
174 }
175}
176
177void PonderingSystem::processCollision(
178 id_type entity,
179 Direction dir,
180 double& newX,
181 double& newY,
182 int axis,
183 MappableComponent::Boundary::Type type)
184{
185 auto& ponderable = game_.getEntityManager().
186 getComponent<PonderableComponent>(entity);
187
188 auto& transformable = game_.getEntityManager().
189 getComponent<TransformableComponent>(entity);
190
191 bool touchedGround = false;
192
193 switch (type)
194 {
195 case MappableComponent::Boundary::Type::wall:
196 {
197 switch (dir)
198 {
199 case Direction::left:
200 {
201 newX = axis;
202 ponderable.setVelocityX(0.0);
203
204 break;
205 }
206
207 case Direction::right:
208 {
209 newX = axis - transformable.getW();
210 ponderable.setVelocityX(0.0);
211
212 break;
213 }
214
215 case Direction::up:
216 {
217 newY = axis;
218 ponderable.setVelocityY(0.0);
219
220 break;
221 }
222
223 case Direction::down:
224 {
225 touchedGround = true;
226
227 break;
228 }
229 }
230
231 break;
232 }
233
234 case MappableComponent::Boundary::Type::platform:
235 {
236 if (game_.getEntityManager().hasComponent<OrientableComponent>(entity))
237 {
238 auto& orientable = game_.getEntityManager().
239 getComponent<OrientableComponent>(entity);
240
241 if (orientable.getDropState() != OrientableComponent::DropState::none)
242 {
243 orientable.setDropState(OrientableComponent::DropState::active);
244 } else {
245 touchedGround = true;
246 }
247 } else {
248 touchedGround = true;
249 }
250
251 break;
252 }
253
254 default:
255 {
256 // Not yet implemented.
257
258 break;
259 }
260 }
261
262 if (touchedGround)
263 {
264 newY = axis - transformable.getH();
265 ponderable.setVelocityY(0.0);
266 ponderable.setGrounded(true);
267 }
268}