Winsock应用中的线性航位推算

use*_*037 4 c++ networking winsock dead-reckoning

我在服务器 - 客户端Winsock游戏中理解我如何实现Dead Reckoning有点困难.

我一直在互联网上寻找一个可靠解释的解释:

  1. 当消息应该从服务器发送到客户端时

  2. 如果客户端没有收到更新消息,它应该如何操作,它是否继续使用预测位置作为当前位置来计算新的预测位置?

我使用的航位推算方法是:

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
Run Code Online (Sandbox Code Playgroud)

希望这是正确的配方!:)

还应注意连接类型是UDP,并且游戏仅在服务器上播放.服务器将更新消息发送到客户端.

有人可以帮我回答我的问题吗?

谢谢

Pro*_*oxy 9

航位推算需要一组变量才能起作用 - 称为运动状态 - 通常包含给定物体的位置,速度,加速度,方向和角速度.如果只查找位置,可以选择忽略方向和角速度.如果您希望预测方向和位置,请发表评论,我会更新我的答案.

这里显示了用于网络游戏的标准航位推算算法:

航位推算方程

上面的变量描述如下:

P t:估计的位置.产量

P O:对象的最新位置更新

V O:对象的最新速度更新

A O:对象的最新加速更新

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

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


一种方法是创建一条直线,甚至更好的曲线,例如Bézier样条 曲线Catmull-Rom样条曲线Hermite曲线(这里列出其他方法的一个很好的列表),两种状态之间仍然将旧方向投射到未来.所以,继续使用旧状态直到你得到一个新状态 - 当你融入的状态变成旧状态时.

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

这个网页引用了"游戏引擎宝石2"一书,是一个推算的金矿:

网络游戏的可信推算

编辑:以上所有内容仅适用于客户端在未获得更新时的行为方式.至于"当一条消息应该从服务器发送到客户端"时,Valve说好的服务器应该以大约15毫秒的间隔发送更新,大约每秒66.6.

注意:" Valve说 "链接实际上也有一些很好的网络技巧,使用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;
}
Run Code Online (Sandbox Code Playgroud)

祝你好运,呃,如果你碰巧在比赛中赚了数百万美元,试着把我放进学分;)

  • @ user2990037只要确保`elapsedSeconds`是'new - old`而不是`new/old` xD (2认同)