我在理解如何在服务器-客户端 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 splines 和 Hermite 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/