【发布时间】:2012-04-22 13:57:59
【问题描述】:
您好,我正在玩 Box2D。我正在开发一款需要与所有身体完全同步的网络游戏。 (不会有很多尸体)。
所以计划是我启动一个服务器,里面有一些机构。服务器执行世界模拟步骤。然后过了一会儿客户端连接。当它这样做时,服务器将世界上所有主体的所有状态数据发送给客户端,客户端将它们创建为新主体。然后客户端将在客户端拥有完全同步的游戏副本。服务器上的任何小的更改都会被复制并作为消息发送到客户端。而且因为 Box2D 是确定性的,服务器端的任何更改都会在客户端表现得完全相同。
如果所有身体都醒着,这将非常有效。但是,当我其中一个人睡着时,模拟变得不同步。睡眠物体的位置、角度和速度只有几位小数。 实际上,他们似乎只需要休息一下就可以搞砸同步。
所以我注意到的是,即使我明确设置一个新的身体进入睡眠状态,在下一个世界步骤之后它会再次醒来。我猜这是因为 Box2D 需要对某种新实体进行检查。
有没有办法解决这个问题?并保持同步?
如果我的校验和检查检测到不同步,目前我每 120 帧重新同步一次所有主体。并继续这样做,直到它们再次不同步。这会导致一些游戏对象的捕捉,但仍然运行得非常好,但 id 宁愿游戏不会首先失去同步。
服务器会将 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);
【问题讨论】:
-
能贴出body创建的代码吗?
-
当然,但我不认为有什么问题。