我在理解如何在服务器-客户端 Winsock 游戏中实现航位推算时有点困难。

我一直在互联网上寻找一个很好的解释,可以准确解释:

  • 何时应该从服务器向客户端发送消息
  • 如果客户端没有收到更新消息,它应该如何操作,它是否继续使用预测位置作为当前位置以计算新的预测位置?

  • 我使用的航位推算方法是:
    path vector = oldPosition - oldestPosition
    delta time = oldTime - oldestTime
    delta velocity = path vector / delta time
    new delta time = current time / oldest time
    new prediction = oldPosition + new delta time * delta velocity
    

    希望这是正确的使用公式! :)

    还应该注意连接类型是 UDP 并且游戏只能在服务器上玩。服务器向客户端发送更新消息。

    任何人都可以帮助回答我的问题吗?

    谢谢

    最佳答案

    航位推算需要一组变量才能发挥作用——称为运动状态——通常包含给定对象的位置、速度、加速度、方向和角速度。如果您只是在寻找位置,您可以选择忽略方向和角速度。如果您想预测方向和位置,请发表评论,我会更新我的答案。

    网络游戏的标准航位推算算法如下所示:

    上述变量的描述如下:

    Pt:估计位置。输出

    PO:对象最近的位置更新

    VO:物体最近的速度更新

    AO:物体最近的加速度更新

    T:当前时间和上次更新的时间戳之间经过的秒数 - 不是收到数据包的时间。

    这可用于移动对象,直到从服务器收到更新。然后,您有两种运动状态:估计位置(上述算法的最新输出)和刚刚接收到的实际位置。现实地混合这两种状态可能很困难。

    一种方法是在两个状态之间创建一条线,或者甚至更好,一条曲线,例如 Bézier splines Catmull-Rom splinesHermite curves (其他方法的一个很好的列表是 here ),同时仍将旧方向投影到 future 。因此,继续使用旧状态,直到获得新状态 - 当您正在融入的状态成为旧状态时。

    另一种技术是使用投影速度混合,这是两个投影的混合 - 最后已知状态和当前状态 - 其中当前渲染位置是给定时间内最后已知和当前速度的混合。

    这个网页引用了“游戏引擎 gem 2”一书,是航位推算的金矿:

    Believable Dead Reckoning for Networked Games

    编辑:以上所有内容仅用于客户端在未获得更新时应如何操作。至于“什么时候应该从服务器向客户端发送消息”,Valve says 一个好的服务器应该以大约 15 毫秒的间隔发送更新,大约每秒 66.6 次。

    注意:“Valve says”链接实际上也有一些很好的网络技巧,使用 Source Multiplayer Networking 作为媒介。有时间的话就去看看吧。

    编辑 2(代码更新!):

    下面是我将如何在 C++/DirectX 环境中实现这样的算法:

    struct kinematicState
    {
         D3DXVECTOR3 position;
         D3DXVECTOR3 velocity;
         D3DXVECTOR3 acceleration;
    };
    
    void PredictPosition(kinematicState *old, kinematicState *prediction, float elapsedSeconds)
    {
         prediction->position = old->position + (old->velocity * elapsedSeconds) + (0.5 * old->acceleration * (elapsedSeconds * elapsedSeconds));`
    }
    
    kinematicState *BlendKinematicStateLinear(kinematicState *olStated, kinematicState *newState, float percentageToNew)
    {
         //Explanation of percentateToNew:
         //A value of 0.0 will return the exact same state as "oldState",
         //A value of 1.0 will return the exact same state as "newState",
         //A value of 0.5 will return a state with data exactly in the middle of that of "old" and "new".
         //Its value should never be outside of [0, 1].
    
         kinematicState *final = new kinematicState();
    
         //Many other interpolation algorithms would create a smoother blend,
         //But this is just a linear interpolation to keep it simple.
    
         //Implementation of a different algorithm should be straightforward.
         //I suggest starting with Catmull-Rom splines.
    
         float percentageToOld = 1.0 - percentageToNew;
    
         final->position = (percentageToOld * oldState->position) + (percentageToNew * new-State>position);
         final->velocity = (percentageToOld * oldState->velocity) + (percentageToNew * newState->velocity);
         final->acceleration = (percentageToOld * oldState->acceleration) + (percentageToNew * newState->acceleration);
    
         return final;
    }
    

    祝你好运,呃,如果你碰巧在游戏中赚了数百万,试着把我放在学分上;)

    关于c++ - Winsock 应用程序中的线性航位推算,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20913611/

    10-10 21:24