diff options
| author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-05-08 21:47:57 -0400 |
|---|---|---|
| committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2018-05-09 17:59:13 -0400 |
| commit | 67b24a8ddd89371cfb944c5b441c852f0edc23b1 (patch) | |
| tree | d52c054e35e680bcc65c0acafc924dc1deb6c50e /src/systems | |
| parent | 5c82f052c26303318e81ddd76475c1d188cc74f4 (diff) | |
| download | therapy-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/systems')
| -rw-r--r-- | src/systems/pondering.cpp | 222 | ||||
| -rw-r--r-- | src/systems/pondering.h | 3 |
2 files changed, 138 insertions, 87 deletions
| 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 | ||
| 86 | void PonderingSystem::tickBody( | 83 | void 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, |
