こんにちは、Box2D を楽しんでいます。そして、私はすべての体との完全な同期を必要とするネットワーク ゲームに取り組んでいます。(多くの体はありません)。
だから計画は、いくつかの体が入ったサーバーを起動することです。サーバーは、ワールド シミュレーションの手順を実行します。しばらくすると、クライアントが接続します。それが行われると、サーバーは世界中のすべてのボディのすべての状態データをクライアントに送信し、クライアントはそれらを新しいボディとして作成します。そして、クライアントは、クライアント側でゲームの正確に完全に同期されたコピーを持ちます。サーバー上の小さな変更はすべてコピーされ、メッセージとしてクライアントに送信されます。また、Box2D は決定論的であるため、サーバー側での変更はクライアントでもまったく同じように動作します。
すべての体が起きている場合、これはうまく機能します。ただし、そのうちの 1 つがスリープ状態になると、シミュレーションが同期されなくなります。眠っている体の位置、角度、速度は、小数点以下の桁数だけ異なります。実際には、同期を台無しにするために休む必要があるようです。
だから私が気づいたのは、新しい体を明示的にスリープ状態に設定したとしても、次のワールドステップの後に再び目覚めるということでした. これは、Box2D が何らかの新しいボディに対してチェックを実行する必要があるためだと思います。
とにかくこれを修正する方法はありますか?そして、同期を維持しますか?
チェックサムチェックでオフシンクが検出された場合、現在、120フレームごとにすべてのボディを再同期しています。再び非同期になるまでそれを続けます。これにより、ゲーム オブジェクトのスナップが発生しますが、それでも驚くほどうまく機能しますが、そもそもゲームが非同期になることはありません。
サーバーは float 値と int 値をクライアントに送信し、クライアントは次のコードを使用して本文を作成します。サーバー側で本文を作成するとき、サーバーはほとんど同じコードを使用します。
//------------create world---------------
b2Vec2 gravity(0.0f, -10.0f);
b2World world(gravity);
world.SetAllowSleeping(true);
//---------------create bodies from values sent by server----------------------
//body def
b2BodyDef bodyDef;
if(bodyType == static_body)
bodyDef.type = b2_staticBody;
else if(bodyType == dynamic_body)
bodyDef.type = b2_dynamicBody;
else
throw "error invalid body def types";
bodyDef.angle = angle;
bodyDef.angularDamping = angularDamping;
bodyDef.angularVelocity = angularVelocity;
bodyDef.gravityScale = gravityScale;
bodyDef.linearDamping = linearDamping;
bodyDef.linearVelocity.x = linearVelocityX;
bodyDef.linearVelocity.y = linearVelocityY;
bodyDef.position.x = positionX;
bodyDef.position.y = positionY;
bodyDef.active = isActive;
bodyDef.awake = isAwake;
bodyDef.bullet = isBullet;
bodyDef.fixedRotation = isFixedRotation;
bodyDef.allowSleep = isSleepingAllowed;
//body
// Call the body factory which allocates memory for the ground body
// from a pool and creates the ground box shape (also from a pool).
// The body is also added to the world.
body = world.CreateBody(&bodyDef);
//fixture def
b2PolygonShape polygonShape;
polygonShape.SetAsBox(shapeWidth, shapeHeight);
b2FixtureDef fixtureDef;
fixtureDef.shape = &polygonShape;
fixtureDef.restitution = 0.5f; // air resistance / fluid resistance
fixtureDef.density = 1.0f;
fixtureDef.friction = 1.0f;
//fixture
body->CreateFixture(&fixtureDef);
//set mass inertia and center
b2MassData md;
md.center = b2Vec2_zero;
md.I = intertia;
md.mass = mass;
body->SetMassData(&md);
//these cannot be predefined for some reason, seems like a bug in box2d
body->SetFixedRotation(isFixedRotation);
//----------run game simulations-----------
float32 timeStep = 1.0f / 60.0f;
int32 velocityIterations = 6;
int32 positionIterations = 2;
world.Step(timeStep, velocityIterations, positionIterations);