summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2018-05-08 21:47:57 -0400
committerKelly Rauchenberger <fefferburbia@gmail.com>2018-05-09 17:59:13 -0400
commit67b24a8ddd89371cfb944c5b441c852f0edc23b1 (patch)
treed52c054e35e680bcc65c0acafc924dc1deb6c50e /src
parent5c82f052c26303318e81ddd76475c1d188cc74f4 (diff)
downloadtherapy-67b24a8ddd89371cfb944c5b441c852f0edc23b1.tar.gz
therapy-67b24a8ddd89371cfb944c5b441c852f0edc23b1.tar.bz2
therapy-67b24a8ddd89371cfb944c5b441c852f0edc23b1.zip
Fixed ferries pushing passengers
Ferries now pretend that their passengers have already moved by the appropriate delta when detecting collision in the direction of their passengers. This allows a ferry to move into the space where their passengers are when there is nothing else blocking it. It also allows for special behavior when a passenger is crushed between its ferry and a wall, but this is not yet implemented.

This fixes the first issue described in 8f1c4f1 -- that ferries cannot push their passengers. With this fix, ferries are basically functional.
Diffstat (limited to 'src')
-rw-r--r--src/components/ponderable.h5
-rw-r--r--src/systems/pondering.cpp222
-rw-r--r--src/systems/pondering.h3
3 files changed, 141 insertions, 89 deletions
diff --git a/src/components/ponderable.h b/src/components/ponderable.h index c0312b4..e6aa976 100644 --- a/src/components/ponderable.h +++ b/src/components/ponderable.h
@@ -5,6 +5,7 @@
5#include "component.h" 5#include "component.h"
6#include "entity_manager.h" 6#include "entity_manager.h"
7#include "vector.h" 7#include "vector.h"
8#include "direction.h"
8 9
9class PonderableComponent : public Component { 10class PonderableComponent : public Component {
10public: 11public:
@@ -84,11 +85,11 @@ public:
84 id_type ferry; 85 id_type ferry;
85 86
86 /** 87 /**
87 * The location of the body relative to the location of its ferry. 88 * The side of the ferry that the body is resting on, if there is one.
88 * 89 *
89 * @managed_by PonderingSystem 90 * @managed_by PonderingSystem
90 */ 91 */
91 vec2d rel = { 0.0, 0.0 }; 92 Direction ferrySide;
92 93
93 /** 94 /**
94 * The bodies that are being ferried by this body. 95 * The bodies that are being ferried by this body.
diff --git a/src/systems/pondering.cpp b/src/systems/pondering.cpp index ec83270..c806cc8 100644 --- a/src/systems/pondering.cpp +++ b/src/systems/pondering.cpp
@@ -31,10 +31,7 @@ void PonderingSystem::tick(double dt)
31 continue; 31 continue;
32 } 32 }
33 33
34 tickBody( 34 tickBody(entity, dt);
35 entity,
36 dt,
37 entities);
38 } 35 }
39} 36}
40 37
@@ -85,8 +82,7 @@ void PonderingSystem::unferry(id_type entity)
85 82
86void PonderingSystem::tickBody( 83void PonderingSystem::tickBody(
87 id_type entity, 84 id_type entity,
88 double dt, 85 double dt)
89 const std::set<id_type>& entities)
90{ 86{
91 auto& ponderable = game_.getEntityManager(). 87 auto& ponderable = game_.getEntityManager().
92 getComponent<PonderableComponent>(entity); 88 getComponent<PonderableComponent>(entity);
@@ -116,14 +112,6 @@ void PonderingSystem::tickBody(
116 112
117 if (!ponderable.frozen) 113 if (!ponderable.frozen)
118 { 114 {
119 if (ponderable.ferried)
120 {
121 auto& ferryTrans = game_.getEntityManager().
122 getComponent<TransformableComponent>(ponderable.ferry);
123
124 newPos = ferryTrans.pos + ponderable.rel;
125 }
126
127 newPos += ponderable.vel * dt; 115 newPos += ponderable.vel * dt;
128 } 116 }
129 117
@@ -171,6 +159,7 @@ void PonderingSystem::tickBody(
171 159
172 ponderable.ferried = true; 160 ponderable.ferried = true;
173 ponderable.ferry = result.groundEntity; 161 ponderable.ferry = result.groundEntity;
162 ponderable.ferrySide = Direction::up;
174 163
175 ferryPonder.passengers.insert(entity); 164 ferryPonder.passengers.insert(entity);
176 } else if (ponderable.ferried) 165 } else if (ponderable.ferried)
@@ -180,67 +169,12 @@ void PonderingSystem::tickBody(
180 } 169 }
181 } 170 }
182 171
183 // Update a ferry passenger's relative position
184 if (ponderable.ferried)
185 {
186 auto& ferryTrans = game_.getEntityManager().
187 getComponent<TransformableComponent>(ponderable.ferry);
188
189 ponderable.rel = transformable.pos - ferryTrans.pos;
190 }
191
192 // Handle ferry passengers 172 // Handle ferry passengers
193 std::set<id_type> passengers = ponderable.passengers; 173 std::set<id_type> passengers = ponderable.passengers;
194 174
195 for (id_type passenger : passengers) 175 for (id_type passenger : passengers)
196 { 176 {
197 tickBody( 177 tickBody(passenger, dt);
198 passenger,
199 dt,
200 entities);
201 }
202
203 // Move to an adjacent map, if necessary
204 if (result.adjacentlyWarping)
205 {
206 vec2d warpPos = result.pos;
207
208 switch (result.adjWarpDir)
209 {
210 case Direction::left:
211 {
212 warpPos.x() = GAME_WIDTH + WALL_GAP - transformable.size.w();
213
214 break;
215 }
216
217 case Direction::right:
218 {
219 warpPos.x() = -WALL_GAP;
220
221 break;
222 }
223
224 case Direction::up:
225 {
226 warpPos.y() = MAP_HEIGHT * TILE_HEIGHT - transformable.size.h();
227
228 break;
229 }
230
231 case Direction::down:
232 {
233 warpPos.y() = -WALL_GAP;
234
235 break;
236 }
237 }
238
239 game_.getSystemManager().getSystem<PlayingSystem>().
240 changeMap(
241 entity,
242 result.adjWarpMapId,
243 warpPos);
244 } 178 }
245} 179}
246 180
@@ -251,9 +185,6 @@ PonderingSystem::CollisionResult PonderingSystem::moveBody(
251 auto& ponderable = game_.getEntityManager(). 185 auto& ponderable = game_.getEntityManager().
252 getComponent<PonderableComponent>(entity); 186 getComponent<PonderableComponent>(entity);
253 187
254 auto& transformable = game_.getEntityManager().
255 getComponent<TransformableComponent>(entity);
256
257 CollisionResult result; 188 CollisionResult result;
258 189
259 if (ponderable.collidable) 190 if (ponderable.collidable)
@@ -263,11 +194,17 @@ PonderingSystem::CollisionResult PonderingSystem::moveBody(
263 result.pos = newPos; 194 result.pos = newPos;
264 } 195 }
265 196
266 // Move
267 if (!ponderable.frozen) 197 if (!ponderable.frozen)
268 { 198 {
199 auto& transformable = game_.getEntityManager().
200 getComponent<TransformableComponent>(entity);
201
202 vec2d delta = result.pos - transformable.pos;
203
204 // Move.
269 transformable.pos = result.pos; 205 transformable.pos = result.pos;
270 206
207 // Stop if the entity hit a wall.
271 if (result.blockedHoriz) 208 if (result.blockedHoriz)
272 { 209 {
273 ponderable.vel.x() = 0.0; 210 ponderable.vel.x() = 0.0;
@@ -277,6 +214,60 @@ PonderingSystem::CollisionResult PonderingSystem::moveBody(
277 { 214 {
278 ponderable.vel.y() = 0.0; 215 ponderable.vel.y() = 0.0;
279 } 216 }
217
218 // Move ferry passengers by the appropriate amount.
219 auto passengers = ponderable.passengers;
220
221 for (id_type passenger : passengers)
222 {
223 auto& passTrans = game_.getEntityManager().
224 getComponent<TransformableComponent>(passenger);
225
226 moveBody(passenger, passTrans.pos + delta);
227 }
228
229 // Move to an adjacent map, if necessary
230 if (result.adjacentlyWarping)
231 {
232 vec2d warpPos = result.pos;
233
234 switch (result.adjWarpDir)
235 {
236 case Direction::left:
237 {
238 warpPos.x() = GAME_WIDTH + WALL_GAP - transformable.size.w();
239
240 break;
241 }
242
243 case Direction::right:
244 {
245 warpPos.x() = -WALL_GAP;
246
247 break;
248 }
249
250 case Direction::up:
251 {
252 warpPos.y() = MAP_HEIGHT * TILE_HEIGHT - transformable.size.h();
253
254 break;
255 }
256
257 case Direction::down:
258 {
259 warpPos.y() = -WALL_GAP;
260
261 break;
262 }
263 }
264
265 game_.getSystemManager().getSystem<PlayingSystem>().
266 changeMap(
267 entity,
268 result.adjWarpMapId,
269 warpPos);
270 }
280 } 271 }
281 272
282 return result; 273 return result;
@@ -506,6 +497,9 @@ void PonderingSystem::detectCollisionsInDirection(
506 auto& transform = game_.getEntityManager(). 497 auto& transform = game_.getEntityManager().
507 getComponent<TransformableComponent>(entity); 498 getComponent<TransformableComponent>(entity);
508 499
500 auto& ponderable = game_.getEntityManager().
501 getComponent<PonderableComponent>(entity);
502
509 bool boundaryCollision = false; 503 bool boundaryCollision = false;
510 504
511 auto boundaries = Param::MapBoundaries(mappable); 505 auto boundaries = Param::MapBoundaries(mappable);
@@ -530,6 +524,26 @@ void PonderingSystem::detectCollisionsInDirection(
530 } 524 }
531 } 525 }
532 526
527 // Find the results of pretending to move the entity's passengers, if there
528 // are any.
529 vec2d delta = result.pos - transform.pos;
530 std::map<id_type, CollisionResult> passResults;
531
532 for (id_type passenger : ponderable.passengers)
533 {
534 auto& passPonder = game_.getEntityManager().
535 getComponent<PonderableComponent>(passenger);
536
537 if (passPonder.ferrySide == Param::Dir)
538 {
539 auto& passTrans = game_.getEntityManager().
540 getComponent<TransformableComponent>(passenger);
541
542 passResults[passenger] =
543 detectCollisions(passenger, passTrans.pos + delta);
544 }
545 }
546
533 // Find a list of potential colliders, sorted so that the closest is 547 // Find a list of potential colliders, sorted so that the closest is
534 // first. 548 // first.
535 std::vector<id_type> colliders; 549 std::vector<id_type> colliders;
@@ -555,33 +569,46 @@ void PonderingSystem::detectCollisionsInDirection(
555 continue; 569 continue;
556 } 570 }
557 571
572 // If the collider is a passenger of the entity, pretend that it has already
573 // moved.
558 auto& colliderTrans = game_.getEntityManager(). 574 auto& colliderTrans = game_.getEntityManager().
559 getComponent<TransformableComponent>(collider); 575 getComponent<TransformableComponent>(collider);
560 576
577 vec2d colliderPos = colliderTrans.pos;
578 vec2i colliderSize = colliderTrans.size;
579
580 if (passResults.count(collider))
581 {
582 colliderPos = passResults[collider].pos;
583 }
584
561 // Check if the entity would move into the potential collider, 585 // Check if the entity would move into the potential collider,
562 if (Param::IsPastAxis( 586 if (Param::IsPastAxis(
563 Param::ObjectAxis(colliderTrans), 587 Param::ObjectAxis(colliderPos, colliderSize),
564 Param::EntityAxis(result.pos, transform.size)) && 588 Param::EntityAxis(result.pos, transform.size)) &&
565 // that it wasn't already colliding, 589 // that it wasn't already colliding,
566 !Param::IsPastAxis( 590 !Param::IsPastAxis(
567 Param::ObjectAxis(colliderTrans), 591 Param::ObjectAxis(colliderPos, colliderSize),
568 Param::EntityAxis(transform)) && 592 Param::EntityAxis(transform)) &&
569 // that the position on the non-axis is in range, 593 // that the position on the non-axis is in range,
570 (Param::NonAxisUpper(colliderTrans.pos, colliderTrans.size) > 594 (Param::NonAxisUpper(colliderPos, colliderSize) >
571 Param::NonAxisLower(result.pos)) && 595 Param::NonAxisLower(result.pos)) &&
572 (Param::NonAxisLower(colliderTrans.pos) < 596 (Param::NonAxisLower(colliderPos) <
573 Param::NonAxisUpper(result.pos, transform.size)) && 597 Param::NonAxisUpper(result.pos, transform.size)) &&
574 // and that the collider is not farther away than the environmental 598 // and that the collider is not farther away than the environmental
575 // boundary. 599 // boundary.
576 (!boundaryCollision || 600 (!boundaryCollision ||
577 Param::AtLeastInAxisSweep( 601 Param::AtLeastInAxisSweep(
578 Param::ObjectAxis(colliderTrans), 602 Param::ObjectAxis(colliderPos, colliderSize),
579 it->first))) 603 it->first)))
580 { 604 {
581 colliders.push_back(collider); 605 colliders.push_back(collider);
582 } 606 }
583 } 607 }
584 608
609 // Sort the potential colliders such that the closest to the axis of movement
610 // is first. When sorting, treat passengers of the entity as having already
611 // moved.
585 std::sort( 612 std::sort(
586 std::begin(colliders), 613 std::begin(colliders),
587 std::end(colliders), 614 std::end(colliders),
@@ -589,12 +616,26 @@ void PonderingSystem::detectCollisionsInDirection(
589 auto& leftTrans = game_.getEntityManager(). 616 auto& leftTrans = game_.getEntityManager().
590 getComponent<TransformableComponent>(left); 617 getComponent<TransformableComponent>(left);
591 618
619 vec2d leftPos = leftTrans.pos;
620
621 if (passResults.count(left))
622 {
623 leftPos = passResults[left].pos;
624 }
625
592 auto& rightTrans = game_.getEntityManager(). 626 auto& rightTrans = game_.getEntityManager().
593 getComponent<TransformableComponent>(right); 627 getComponent<TransformableComponent>(right);
594 628
629 vec2d rightPos = rightTrans.pos;
630
631 if (passResults.count(right))
632 {
633 rightPos = passResults[right].pos;
634 }
635
595 return Param::Closer( 636 return Param::Closer(
596 Param::ObjectAxis(leftTrans), 637 Param::ObjectAxis(leftPos, leftTrans.size),
597 Param::ObjectAxis(rightTrans)); 638 Param::ObjectAxis(rightPos, rightTrans.size));
598 }); 639 });
599 640
600 for (id_type collider : colliders) 641 for (id_type collider : colliders)
@@ -602,14 +643,25 @@ void PonderingSystem::detectCollisionsInDirection(
602 auto& colliderTrans = game_.getEntityManager(). 643 auto& colliderTrans = game_.getEntityManager().
603 getComponent<TransformableComponent>(collider); 644 getComponent<TransformableComponent>(collider);
604 645
646 // If the collider is a passenger of the entity, pretend that it has already
647 // moved.
648 vec2d colliderPos = colliderTrans.pos;
649 vec2i colliderSize = colliderTrans.size;
650
651 if (passResults.count(collider))
652 {
653 colliderPos = passResults[collider].pos;
654 }
655
605 // Check if the entity would still move into the potential collider. 656 // Check if the entity would still move into the potential collider.
606 if (!Param::IsPastAxis( 657 if (!Param::IsPastAxis(
607 Param::ObjectAxis(colliderTrans), 658 Param::ObjectAxis(colliderPos, colliderSize),
608 Param::EntityAxis(result.pos, transform.size))) 659 Param::EntityAxis(result.pos, transform.size)))
609 { 660 {
610 break; 661 break;
611 } 662 }
612 663
664 // TODO: Check if the entity is moving into one of its passengers.
613 auto& colliderPonder = game_.getEntityManager(). 665 auto& colliderPonder = game_.getEntityManager().
614 getComponent<PonderableComponent>(collider); 666 getComponent<PonderableComponent>(collider);
615 667
@@ -618,9 +670,9 @@ void PonderingSystem::detectCollisionsInDirection(
618 collider, 670 collider,
619 Param::Dir, 671 Param::Dir,
620 colliderPonder.colliderType, 672 colliderPonder.colliderType,
621 Param::ObjectAxis(colliderTrans), 673 Param::ObjectAxis(colliderPos, colliderSize),
622 Param::NonAxisLower(colliderTrans.pos), 674 Param::NonAxisLower(colliderPos),
623 Param::NonAxisUpper(colliderTrans.pos, colliderTrans.size), 675 Param::NonAxisUpper(colliderPos, colliderSize),
624 result); 676 result);
625 677
626 if (result.stopProcessing) 678 if (result.stopProcessing)
diff --git a/src/systems/pondering.h b/src/systems/pondering.h index 273db67..c79bbf6 100644 --- a/src/systems/pondering.h +++ b/src/systems/pondering.h
@@ -51,8 +51,7 @@ private:
51 51
52 void tickBody( 52 void tickBody(
53 id_type entity, 53 id_type entity,
54 double dt, 54 double dt);
55 const std::set<id_type>& entities);
56 55
57 CollisionResult moveBody( 56 CollisionResult moveBody(
58 id_type entity, 57 id_type entity,