| 262 | |
| 263 | |
| 264 | void olc::rcw::Engine::Update(float fElapsedTime) |
| 265 | { |
| 266 | // Update the position and statically resolve for collisions against the map |
| 267 | for (auto& ob : mapObjects) |
| 268 | { |
| 269 | std::shared_ptr<olc::rcw::Object> object = ob.second; |
| 270 | if (!object->bIsActive) continue; |
| 271 | |
| 272 | int nSteps = 1; |
| 273 | float fDelta = fElapsedTime; |
| 274 | float fTotalTravel = (object->vel * fElapsedTime).mag2(); |
| 275 | float fTotalRadius = (object->fRadius * object->fRadius); |
| 276 | |
| 277 | if(fTotalTravel >= fTotalRadius) |
| 278 | { |
| 279 | float fSteps = std::ceil(fTotalTravel / fTotalRadius); |
| 280 | nSteps = int(fSteps); |
| 281 | fDelta = fElapsedTime / fSteps; |
| 282 | } |
| 283 | |
| 284 | for (int nStep = 0; nStep < nSteps; nStep++) |
| 285 | { |
| 286 | // Determine where object is trying to be |
| 287 | olc::vf2d vPotentialPosition = object->pos + object->vel * fDelta; |
| 288 | |
| 289 | // If the object can collide with other objects |
| 290 | if (object->bCollideWithObjects) |
| 291 | { |
| 292 | // Iterate through all other objects (this can be costly) |
| 293 | for (auto& ob2 : mapObjects) |
| 294 | { |
| 295 | std::shared_ptr<olc::rcw::Object> target = ob2.second; |
| 296 | |
| 297 | // Ignore if target object cant interact |
| 298 | if (!target->bCollideWithObjects) continue; |
| 299 | |
| 300 | // Don't test against self |
| 301 | if (target == object) continue; |
| 302 | |
| 303 | // Quick check to see if objects overlap... |
| 304 | if ((target->pos - object->pos).mag2() <= (target->fRadius + object->fRadius) * (target->fRadius + object->fRadius)) |
| 305 | { |
| 306 | // ..they do. Calculate displacement required |
| 307 | float fDistance = (target->pos - object->pos).mag(); |
| 308 | float fOverlap = 1.0f * (fDistance - object->fRadius - target->fRadius); |
| 309 | |
| 310 | // Object will always give way to target |
| 311 | vPotentialPosition -= (object->pos - target->pos) / fDistance * fOverlap; |
| 312 | |
| 313 | if (target->bCanBeMoved) |
| 314 | target->pos += (object->pos - target->pos) / fDistance * fOverlap; |
| 315 | |
| 316 | if (object->bNotifyObjectCollision) |
| 317 | HandleObjectVsObject(object, target); |
| 318 | } |
| 319 | |
| 320 | |
| 321 | } |