首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >客户端-服务器博弈的算法

客户端-服务器博弈的算法
EN

Stack Overflow用户
提问于 2009-05-01 15:38:44
回答 6查看 8.2K关注 0票数 16

对于独立游戏,基本的游戏循环是(来源:维基百科)

代码语言:javascript
复制
while( user doesn't exit )
  check for user input
  run AI
  move enemies
  resolve collisions
  draw graphics
  play sounds
end while

但如果我开发类似客户端-服务器的游戏,如Quake、Ragnarock、Trackmania等,

游戏中客户端和服务器部分的Loop/Algorithm是什么?

EN

回答 6

Stack Overflow用户

发布于 2009-05-01 15:51:06

它应该是这样的

客户端:

代码语言:javascript
复制
while( user does not exit )
    check for user input
    send commands to the server
    receive updates about the game from the server
    draw graphics
    play sounds
end

服务器:

代码语言:javascript
复制
while( true )
    check for client commands
    run AI
    move all entities
    resolve collisions
    send updates about the game to the clients
end
票数 20
EN

Stack Overflow用户

发布于 2009-05-01 16:25:32

客户端:

代码语言:javascript
复制
connect to server
while( user does not exit && connection live)
    check for user input
    send commands to the server
    estimate outcome and update world data with 'best guess'
    draw graphics
    play sounds
    receive updates about the game from the server
    correct any errors in world data
    draw graphics
    play sounds
end

服务器:

代码语言:javascript
复制
while( true )
    check for and handle new player connections
    check for client commands
    sanity check client commands
    run AI
    move all entities
    resolve collisions
    sanity check world data
    send updates about the game to the clients
    handle client disconnects
end

对客户端命令和世界数据的健全性检查是为了消除任何“不可能”的情况,这些情况要么是故意作弊(移动太快,穿过墙壁等),要么是滞后(穿过客户端认为是打开的门,但服务器知道是关闭的,等等)。

为了处理客户端和服务器之间的延迟,客户端必须对接下来会发生什么做出最好的猜测(使用它的当前世界数据和客户端命令)-客户端将不得不处理它预测的将发生的事情和服务器后来告诉它实际发生的事情之间的任何差异。通常情况下,这将足够接近,以至于玩家不会注意到差异-但如果滞后很明显,或者客户端和服务器不同步(例如,由于作弊),那么当客户端从服务器接收回数据时,它将需要进行突然更正。

为了优化响应时间,将这些进程的各个部分拆分到单独的线程中也有很多问题。

最好的开始方法之一是从一个活跃的修改社区的游戏中获取一个SDK -深入研究它是如何工作的,将提供一个很好的概述。

票数 12
EN

Stack Overflow用户

发布于 2009-05-01 16:06:03

这真的不是一个简单的问题。在最基本的级别上,您可以说网络提供的数据与原始循环的MoveEnemies部分提供的数据相同。因此,您可以简单地将您的循环替换为:

代码语言:javascript
复制
while( user doesn't exit )
  check for user input
  run AI
  send location to server
  get locations from server
  resolve collisions
  draw graphics
  play sounds
end while

但是,您需要考虑延迟,因此您不会真的希望在调用网络时暂停您的主循环。为了克服这一点,经常会看到网络引擎处于第二个线程上,以最快的速度从服务器轮询数据,并将对象的新位置放到共享内存空间中:

代码语言:javascript
复制
while(connectedToNetwork)
    Read player location
    Post player location to server
    Read enemy locations from server
    Post enemy locations into shared memory

然后,您的主循环将如下所示:

代码语言:javascript
复制
while( user doesn't exit )
  check for user input
  run AI
  read/write shared memory
  resolve collisions
  draw graphics
  play sounds
end while

这种方法的优点是,您的游戏循环将尽可能快地运行,但只有在完成与服务器之间的完整post后,才会更新来自服务器的信息。当然,你现在遇到了跨线程共享对象的问题,以及锁等带来的乐趣。

在服务器端,循环基本相同,每个玩家都有一个连接(通常每个玩家也在一个单独的线程上,所以其中一个的延迟不会影响其他的),每个连接都会运行一个循环,如下所示

代码语言:javascript
复制
while (PlayerConnected)
    Wait for player to post location
    Place new location in shared memory

当客户机请求敌人的位置时,服务器从共享内存块中读取所有其他玩家的位置并将其发回。

这是一个非常简单的概述,还有更多的调整可以提高性能(例如,可能值得服务器将敌人的位置发送给客户端,而不是客户端请求它们),您需要决定在哪里做出某些逻辑决定(客户端是因为他自己有最新的位置而决定自己被射杀,还是服务器停止作弊)

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/811906

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档