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.cpp347
1 files changed, 234 insertions, 113 deletions
diff --git a/src/systems/pondering.cpp b/src/systems/pondering.cpp index 4a165b1..2490dc9 100644 --- a/src/systems/pondering.cpp +++ b/src/systems/pondering.cpp
@@ -1,11 +1,14 @@
1#include "pondering.h" 1#include "pondering.h"
2#include <queue>
2#include "game.h" 3#include "game.h"
3#include "components/ponderable.h" 4#include "components/ponderable.h"
4#include "components/transformable.h" 5#include "components/transformable.h"
5#include "components/orientable.h" 6#include "components/orientable.h"
6#include "components/mappable.h" 7#include "components/mappable.h"
7#include "systems/orienting.h" 8#include "systems/orienting.h"
9#include "systems/playing.h"
8#include "consts.h" 10#include "consts.h"
11#include "collision.h"
9 12
10void PonderingSystem::tick(double dt) 13void PonderingSystem::tick(double dt)
11{ 14{
@@ -42,6 +45,9 @@ void PonderingSystem::tick(double dt)
42 bool oldGrounded = ponderable.isGrounded(); 45 bool oldGrounded = ponderable.isGrounded();
43 ponderable.setGrounded(false); 46 ponderable.setGrounded(false);
44 47
48 std::priority_queue<Collision> collisions;
49
50 // Find collisions
45 for (id_type mapEntity : maps) 51 for (id_type mapEntity : maps)
46 { 52 {
47 auto& mappable = game_.getEntityManager(). 53 auto& mappable = game_.getEntityManager().
@@ -57,13 +63,13 @@ void PonderingSystem::tick(double dt)
57 && (oldY < it->second.getUpper())) 63 && (oldY < it->second.getUpper()))
58 { 64 {
59 // We have a collision! 65 // We have a collision!
60 processCollision( 66 collisions.emplace(
61 entity, 67 mapEntity,
62 Direction::left, 68 Direction::left,
63 newX, 69 it->second.getType(),
64 newY,
65 it->first, 70 it->first,
66 it->second.getType()); 71 it->second.getLower(),
72 it->second.getUpper());
67 } 73 }
68 } 74 }
69 } else if (newX > oldX) 75 } else if (newX > oldX)
@@ -77,13 +83,13 @@ void PonderingSystem::tick(double dt)
77 && (oldY < it->second.getUpper())) 83 && (oldY < it->second.getUpper()))
78 { 84 {
79 // We have a collision! 85 // We have a collision!
80 processCollision( 86 collisions.emplace(
81 entity, 87 mapEntity,
82 Direction::right, 88 Direction::right,
83 newX, 89 it->second.getType(),
84 newY,
85 it->first, 90 it->first,
86 it->second.getType()); 91 it->second.getLower(),
92 it->second.getUpper());
87 } 93 }
88 } 94 }
89 } 95 }
@@ -98,13 +104,13 @@ void PonderingSystem::tick(double dt)
98 && (oldX < it->second.getUpper())) 104 && (oldX < it->second.getUpper()))
99 { 105 {
100 // We have a collision! 106 // We have a collision!
101 processCollision( 107 collisions.emplace(
102 entity, 108 mapEntity,
103 Direction::up, 109 Direction::up,
104 newX, 110 it->second.getType(),
105 newY,
106 it->first, 111 it->first,
107 it->second.getType()); 112 it->second.getLower(),
113 it->second.getUpper());
108 } 114 }
109 } 115 }
110 } else if (newY > oldY) 116 } else if (newY > oldY)
@@ -118,13 +124,221 @@ void PonderingSystem::tick(double dt)
118 && (oldX < it->second.getUpper())) 124 && (oldX < it->second.getUpper()))
119 { 125 {
120 // We have a collision! 126 // We have a collision!
121 processCollision( 127 collisions.emplace(
122 entity, 128 mapEntity,
123 Direction::down, 129 Direction::down,
124 newX, 130 it->second.getType(),
125 newY,
126 it->first, 131 it->first,
127 it->second.getType()); 132 it->second.getLower(),
133 it->second.getUpper());
134 }
135 }
136 }
137 }
138
139 // Process collisions in order of priority
140 while (!collisions.empty())
141 {
142 Collision collision = collisions.top();
143 collisions.pop();
144
145 // Make sure that they are still colliding
146 if (!collision.isColliding(
147 newX,
148 newY,
149 transformable.getW(),
150 transformable.getH()))
151 {
152 continue;
153 }
154
155 bool touchedWall = false;
156 bool stopProcessing = false;
157
158 switch (collision.getType())
159 {
160 case Collision::Type::wall:
161 {
162 touchedWall = true;
163
164 break;
165 }
166
167 case Collision::Type::platform:
168 {
169 if (game_.getEntityManager().
170 hasComponent<OrientableComponent>(entity))
171 {
172 auto& orientable = game_.getEntityManager().
173 getComponent<OrientableComponent>(entity);
174
175 if (orientable.getDropState() !=
176 OrientableComponent::DropState::none)
177 {
178 orientable.setDropState(OrientableComponent::DropState::active);
179 } else {
180 touchedWall = true;
181 }
182 } else {
183 touchedWall = true;
184 }
185
186 break;
187 }
188
189 case Collision::Type::adjacency:
190 {
191 auto& mappable = game_.getEntityManager().
192 getComponent<MappableComponent>(collision.getCollider());
193 const Map& map = game_.getWorld().getMap(mappable.getMapId());
194 auto& adj = [&] () -> const Map::Adjacent& {
195 switch (collision.getDirection())
196 {
197 case Direction::left: return map.getLeftAdjacent();
198 case Direction::right: return map.getRightAdjacent();
199 case Direction::up: return map.getUpAdjacent();
200 case Direction::down: return map.getDownAdjacent();
201 }
202 }();
203
204 switch (adj.getType())
205 {
206 case Map::Adjacent::Type::wall:
207 {
208 touchedWall = true;
209
210 break;
211 }
212
213 case Map::Adjacent::Type::wrap:
214 {
215 switch (collision.getDirection())
216 {
217 case Direction::left:
218 {
219 newX = GAME_WIDTH + WALL_GAP - transformable.getW();
220
221 break;
222 }
223
224 case Direction::right:
225 {
226 newX = -WALL_GAP;
227
228 break;
229 }
230
231 case Direction::up:
232 {
233 newY = MAP_HEIGHT * TILE_HEIGHT + WALL_GAP -
234 transformable.getH();
235
236 break;
237 }
238
239 case Direction::down:
240 {
241 newY = -WALL_GAP;
242
243 break;
244 }
245 }
246 }
247
248 case Map::Adjacent::Type::warp:
249 {
250 double warpX = newX;
251 double warpY = newY;
252
253 switch (collision.getDirection())
254 {
255 case Direction::left:
256 {
257 warpX = GAME_WIDTH + WALL_GAP - transformable.getW();
258
259 break;
260 }
261
262 case Direction::right:
263 {
264 warpX = -WALL_GAP;
265
266 break;
267 }
268
269 case Direction::up:
270 {
271 warpY = MAP_HEIGHT * TILE_HEIGHT - transformable.getH();
272
273 break;
274 }
275
276 case Direction::down:
277 {
278 warpY = -WALL_GAP;
279
280 break;
281 }
282 }
283
284 game_.getSystemManager().getSystem<PlayingSystem>().
285 changeMap(adj.getMapId(), warpX, warpY);
286
287 stopProcessing = true;
288
289 break;
290 }
291 }
292 }
293
294 default:
295 {
296 // Not yet implemented.
297
298 break;
299 }
300 }
301
302 if (stopProcessing)
303 {
304 break;
305 }
306
307 if (touchedWall)
308 {
309 switch (collision.getDirection())
310 {
311 case Direction::left:
312 {
313 newX = collision.getAxis();
314 ponderable.setVelocityX(0.0);
315
316 break;
317 }
318
319 case Direction::right:
320 {
321 newX = collision.getAxis() - transformable.getW();
322 ponderable.setVelocityX(0.0);
323
324 break;
325 }
326
327 case Direction::up:
328 {
329 newY = collision.getAxis();
330 ponderable.setVelocityY(0.0);
331
332 break;
333 }
334
335 case Direction::down:
336 {
337 newY = collision.getAxis() - transformable.getH();
338 ponderable.setVelocityY(0.0);
339 ponderable.setGrounded(true);
340
341 break;
128 } 342 }
129 } 343 }
130 } 344 }
@@ -173,96 +387,3 @@ void PonderingSystem::initializeBody(
173 ponderable.setAccelY(NORMAL_GRAVITY); 387 ponderable.setAccelY(NORMAL_GRAVITY);
174 } 388 }
175} 389}
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}