Determinism and State Synchronization
The love.physics wrapper does not provide internal mechanisms to enforce cross-platform determinism. Because it wraps Box2D, it is subject to the floating-point inconsistencies inherent in different CPU architectures, compiler optimizations, and operating systems. Even with a fixed time step, identical inputs on different machines may result in slightly different floating-point results, leading to simulation drift over time.
State Recovery and Serialization
Since love.physics does not provide a native "snapshot" or serialization function for the entire world, you must manually iterate through the physics bodies to synchronize state. To ensure exact recovery, you must synchronize both the linear and angular components of every active body.
The recommended approach for state synchronization is as follows:
- Iterate Bodies: Loop through all bodies in the
love.physics.World.
- Capture Transform: Store the current position
(x, y) and angle (theta).
- Capture Dynamics: Store the linear velocity
(vx, vy) and angular velocity (omega).
- Apply State: On the receiving client, use
body:setPosition(x, y) and body:setLinearVelocity(vx, vy), followed by body:setAngle(theta) and body:setAngularVelocity(omega).
Implementation Considerations
To minimize visual jitter during synchronization, avoid snapping positions every frame. Instead, implement linear interpolation (lerp) between the current local state and the authoritative server state.
-- Example: Manual state capture for a single body
local state = {
x = body:getX(),
y = body:getY(),
angle = body:getAngle(),
vx = body:getLinearVelocityX(),
vy = body:getLinearVelocityY(),
omega = body:getAngularVelocity()
}
Assumptions and Verification
This approach assumes you are using a standard LÖVE release (e.g., 11.x) where love.physics maps directly to Box2D. To verify if your divergence is caused by the time step or floating-point drift, run two instances of the game on the same machine with identical inputs; if they diverge, the issue is likely the time step integration. If they only diverge across different hardware, it is a floating-point determinism issue.
Missing Diagnostic: Are you currently using a fixed accumulator for your love.update(dt) loop, or are you passing the raw dt directly into love.physics.update(dt)?