ElSajko
ElSajko

Reputation: 1640

Fully replicable Javascript Physic 2D engine for netplay

Is there any fully replicable Javascript Physic 2D engine, so we can save state of simulation as a byte array for example, and load it in another machine (same architecture) so both simulation will do same next steps?

I've already heard, Box2D have some (caching?) data that we can't store along with bodies/forces/joints etc.

Upvotes: 1

Views: 509

Answers (1)

schteppe
schteppe

Reputation: 2084

From my experience, full replication of the physics engine state is difficult and unnecessary.

For real time multiplayer games, you usually run a local physics simulation and make corrections to it if the state (positions, rotations, velocities) differ too much from the server state. Unreal Engine uses this approach, read more at https://docs.unrealengine.com/udk/Three/NetworkingOverview.html#Physics

Games that only need the initial state of a physics scene to carry out an animation (such as turn based games), don't need the full physics engine state either. Physics engines are deterministic if you use them in a deterministic way. To re-play a physics animation the same way on two clients, keep in mind:

  • Reset (re-create) the b2World before starting the simulation, to get rid of any internal state in the b2World.
  • Set up your physics world, create bodies at their initial positions, etc.
  • Step the simulation forward, using the same fixed time step on all clients (don't use the render frame delta time because it's not the same on all clients!).
  • If you need to interact with the bodies during simulation (for example, apply a force), then it's important to do it on the same step number.

As an example, the following function will return the same result every time on all clients, if they all get the same InitialPhysicsState:

float deterministicFunction( InitialPhysicsState state ){
    b2World* world = createWorld(state);
    b2Body* body = world->GetBodyList();
    for(int i=0; i<100; i++){
        if(i==50){
            body->ApplyForce(b2Vec2(10.0f, 2.0f));
        }
        world->Step(0.01f, 8, 3);
    }
    return body->GetPosition().y;
}

Upvotes: 2

Related Questions