Added dynamic step size for collision tests

pull/173/head
Javidx9 4 years ago committed by GitHub
parent 43c1ddc6b3
commit 6041b4b677
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 34
      Extensions/olcPGEX_RayCastWorld.h

@ -3,7 +3,7 @@
+-------------------------------------------------------------+ +-------------------------------------------------------------+
| OneLoneCoder Pixel Game Engine Extension | | OneLoneCoder Pixel Game Engine Extension |
| Ray Cast World v1.01 | | Ray Cast World v1.02 |
+-------------------------------------------------------------+ +-------------------------------------------------------------+
NOTE: UNDER ACTIVE DEVELOPMENT - THERE ARE BUGS/GLITCHES NOTE: UNDER ACTIVE DEVELOPMENT - THERE ARE BUGS/GLITCHES
@ -65,6 +65,11 @@
Author Author
~~~~~~ ~~~~~~
David Barr, aka javidx9, ©OneLoneCoder 2019, 2020 David Barr, aka javidx9, ©OneLoneCoder 2019, 2020
Revisions:
1.00: Initial Release
1.01: Fix NaN check on overlap distance (Thanks Dandistine)
1.02: Added dynamic step size for collisions
*/ */
#ifndef OLC_PGEX_RAYCASTWORLD_H #ifndef OLC_PGEX_RAYCASTWORLD_H
@ -262,8 +267,22 @@ void olc::rcw::Engine::Update(float fElapsedTime)
std::shared_ptr<olc::rcw::Object> object = ob.second; std::shared_ptr<olc::rcw::Object> object = ob.second;
if (!object->bIsActive) continue; if (!object->bIsActive) continue;
int nSteps = 1;
float fDelta = fElapsedTime;
float fTotalTravel = (object->vel * fElapsedTime).mag2();
float fTotalRadius = (object->fRadius * object->fRadius);
if(fTotalTravel >= fTotalRadius)
{
float fSteps = std::ceil(fTotalTravel / fTotalRadius);
nSteps = int(fSteps);
fDelta = fElapsedTime / fSteps;
}
for (int nStep = 0; nStep < nSteps; nStep++)
{
// Determine where object is trying to be // Determine where object is trying to be
olc::vf2d vPotentialPosition = object->pos + object->vel * fElapsedTime; olc::vf2d vPotentialPosition = object->pos + object->vel * fDelta;
// If the object can collide with other objects // If the object can collide with other objects
if (object->bCollideWithObjects) if (object->bCollideWithObjects)
@ -284,12 +303,12 @@ void olc::rcw::Engine::Update(float fElapsedTime)
{ {
// ..they do. Calculate displacement required // ..they do. Calculate displacement required
float fDistance = (target->pos - object->pos).mag(); float fDistance = (target->pos - object->pos).mag();
float fOverlap = 1.0f * ( fDistance - object->fRadius - target->fRadius); float fOverlap = 1.0f * (fDistance - object->fRadius - target->fRadius);
// Object will always give way to target // Object will always give way to target
vPotentialPosition -= (object->pos - target->pos) / fDistance * fOverlap; vPotentialPosition -= (object->pos - target->pos) / fDistance * fOverlap;
if(target->bCanBeMoved) if (target->bCanBeMoved)
target->pos += (object->pos - target->pos) / fDistance * fOverlap; target->pos += (object->pos - target->pos) / fDistance * fOverlap;
if (object->bNotifyObjectCollision) if (object->bNotifyObjectCollision)
@ -311,6 +330,8 @@ void olc::rcw::Engine::Update(float fElapsedTime)
olc::vi2d vAreaBR = { std::max(vCurrentCell.x, vTargetCell.x) + 1, std::max(vCurrentCell.y, vTargetCell.y) + 1 }; olc::vi2d vAreaBR = { std::max(vCurrentCell.x, vTargetCell.x) + 1, std::max(vCurrentCell.y, vTargetCell.y) + 1 };
// Iterate through each cell in test area // Iterate through each cell in test area
olc::vi2d vCell; olc::vi2d vCell;
for (vCell.y = vAreaTL.y; vCell.y <= vAreaBR.y; vCell.y++) for (vCell.y = vAreaTL.y; vCell.y <= vAreaBR.y; vCell.y++)
@ -334,12 +355,12 @@ void olc::rcw::Engine::Update(float fElapsedTime)
// But modified to work :P // But modified to work :P
olc::vf2d vRayToNearest = vNearestPoint - vPotentialPosition; olc::vf2d vRayToNearest = vNearestPoint - vPotentialPosition;
float fOverlap = object->fRadius - vRayToNearest.mag(); float fOverlap = object->fRadius - vRayToNearest.mag();
if(std::isnan(fOverlap)) fOverlap = 0;// Thanks Dandistine! if (std::isnan(fOverlap)) fOverlap = 0;// Thanks Dandistine!
// If overlap is positive, then a collision has occurred, so we displace backwards by the // If overlap is positive, then a collision has occurred, so we displace backwards by the
// overlap amount. The potential position is then tested against other tiles in the area // overlap amount. The potential position is then tested against other tiles in the area
// therefore "statically" resolving the collision // therefore "statically" resolving the collision
if ( fOverlap > 0) if (fOverlap > 0)
{ {
// Statically resolve the collision // Statically resolve the collision
vPotentialPosition = vPotentialPosition - vRayToNearest.norm() * fOverlap; vPotentialPosition = vPotentialPosition - vRayToNearest.norm() * fOverlap;
@ -364,6 +385,7 @@ void olc::rcw::Engine::Update(float fElapsedTime)
// Set the objects new position to the allowed potential position // Set the objects new position to the allowed potential position
object->pos = vPotentialPosition; object->pos = vPotentialPosition;
} }
}
} }
void olc::rcw::Engine::Render() void olc::rcw::Engine::Render()

Loading…
Cancel
Save