The ground has to hold still while everything falls onto it. Today you make a body with zero inverse mass ignore forces entirely, so statics and dynamics can share one world.
Skip integration for a body whose inverse mass is zero, so no force can move it.
A world holds two kinds of bodies: dynamic ones that respond to forces and
collisions, and static ones - the ground, walls, platforms - that never move.
The inverse mass you just built is the switch between them: a static body has
InvMass == 0, so the cleanest way to keep it still is to skip integration for it
entirely. Applying a force to it does nothing; even a huge force leaves it exactly
where it started.
Guard the step on InvMass == 0 and return early, clearing any accumulated force so
it does not pile up. This is also why static bodies must be created with SetMass(0)
rather than a normal mass - it is what sets the zero inverse mass the guard checks.
For the dynamic body, the same force divided by mass 2 gives acceleration
{0, -50}, so after one second it is falling at {0, -50} and has dropped to
{5, -45}. One world, two behaviors, one field telling them apart.
func stepBody(b *Body, dt float64) {if b.InvMass == 0 { // static: never moves, just drop accumulated forceb.ClearForces()return}b.Acceleration = b.accelerationFromForce()b.Integrate(dt)b.ClearForces()}