| 475 | } |
| 476 | |
| 477 | void MovementController::tickMaster(float dt) { |
| 478 | setTimestep(dt); |
| 479 | auto geometry = world()->geometry(); |
| 480 | |
| 481 | m_zeroG.set(!*m_parameters.gravityEnabled || *m_parameters.gravityMultiplier == 0 || world()->gravity(position()) == 0); |
| 482 | |
| 483 | Maybe<PhysicsMovingCollision> surfaceCollision; |
| 484 | if (auto movingCollisionId = m_surfaceMovingCollision.get()) { |
| 485 | if (auto physicsEntity = world()->get<PhysicsEntity>(movingCollisionId->physicsEntityId)) |
| 486 | surfaceCollision = physicsEntity->movingCollision(movingCollisionId->collisionIndex); |
| 487 | } |
| 488 | |
| 489 | if (surfaceCollision) { |
| 490 | Vec2F surfacePositionDelta = geometry.diff(surfaceCollision->position, m_surfaceMovingCollisionPosition); |
| 491 | setPosition(position() + surfacePositionDelta); |
| 492 | Vec2F newSurfaceVelocity = surfacePositionDelta / dt; |
| 493 | setVelocity(velocity() - m_surfaceVelocity + newSurfaceVelocity); |
| 494 | m_surfaceVelocity = newSurfaceVelocity; |
| 495 | } else { |
| 496 | m_surfaceMovingCollision.set({}); |
| 497 | m_surfaceMovingCollisionPosition = {}; |
| 498 | m_surfaceVelocity = {}; |
| 499 | } |
| 500 | |
| 501 | if (m_resting) { |
| 502 | m_restTicks -= 1; |
| 503 | if (m_restTicks < 0) { |
| 504 | m_resting = false; |
| 505 | } |
| 506 | } |
| 507 | |
| 508 | // don't integrate velocity when resting |
| 509 | Vec2F relativeVelocity = m_resting ? Vec2F() : velocity(); |
| 510 | Vec2F originalMovement = relativeVelocity * dt; |
| 511 | if (surfaceCollision) |
| 512 | relativeVelocity -= m_surfaceVelocity; |
| 513 | |
| 514 | m_collisionCorrection = {}; |
| 515 | m_surfaceSlope = Vec2F(1, 0); |
| 516 | m_surfaceMovingCollision.set({}); |
| 517 | |
| 518 | unsigned steps; |
| 519 | float maxMovementPerStep = *m_parameters.maxMovementPerStep; |
| 520 | if (maxMovementPerStep > 0.0f) |
| 521 | steps = std::floor(vmag(relativeVelocity) * dt / maxMovementPerStep) + 1; |
| 522 | else |
| 523 | steps = 1; |
| 524 | |
| 525 | // skip collision checks when resting (there's no movement anyway) |
| 526 | if (m_resting) |
| 527 | steps = 0; |
| 528 | |
| 529 | for (unsigned i = 0; i < steps; ++i) { |
| 530 | float dtSteps = dt / steps; |
| 531 | Vec2F movement = relativeVelocity * dtSteps; |
| 532 | |
| 533 | if (!*m_parameters.collisionEnabled || collisionPoly().isNull()) { |
| 534 | setPosition(position() + movement); |
nothing calls this directly
no test coverage detected