struct Impulse { Vector2 force = { 0, 0 }; float32 timeOfApplicationSeconds = 0.25f; float32 timeAppliedSeconds = 0.f; bool isDead = false; }; const int32 NUM_IMPULSES = 4; struct Rigidbody { int32 numImpulses = 0; Impulse activeImpulses[NUM_IMPULSES]; Vector2 velocity = { 0, 0 }; Vector2 position = { 0, 0 }; float32 mass = 1.f; void update(float32 deltaTimeSeconds) { applyGravity(deltaTimeSeconds); Vector2 force; for (int32 idx = 0; idx < numImpulses; idx++) { Impulse& i = activeImpulses[idx]; float32 nextTimeAppliedSeconds = i.timeAppliedSeconds + deltaTimeSeconds; if (nextTimeAppliedSeconds >= i.timeOfApplicationSeconds) { nextTimeAppliedSeconds = i.timeOfApplicationSeconds; // Do the remainder of the time i.isDead = true; } // We apply the force spread out over timeOfApplicationSeconds, so we need // to calculate the fractional amount of force that was applied in this frame. float32 impulseDtSeconds = nextTimeAppliedSeconds - i.timeAppliedSeconds; Vector2 forceToApply = i.force * (impulseDtSeconds / i.timeOfApplicationSeconds); force += forceToApply * impulseDtSeconds; i.timeAppliedSeconds = nextTimeAppliedSeconds; } Vector2 acceleration = force / mass; velocity += (acceleration * deltaTimeSeconds); position += (velocity * deltaTimeSeconds); // Cleanup any impulses that have expired in the mean time for (int32 idx = 0; idx < numImpulses; idx++) { if (activeImpulses[idx].isDead) { for (int j = idx + 1; j < numImpulses; j++) { activeImpulses[j - 1] = activeImpulses[j]; } idx = idx - 1; numImpulses--; } } } void applyGravity(float32 deltaTimeSeconds) { velocity += (Vector2 { 0.f, -9.8f } * deltaTimeSeconds); } void applyImpulse(Impulse i) { if (numImpulses > NUM_IMPULSES) { printf("Unable to apply impulse. Buffer full.\n"); return; } activeImpulses[numImpulses] = i; numImpulses++; } };