带有JavaScript后端和前端的多人游戏。 什么是最佳实践?
我正在考虑在Node.js中创build一个Web多人游戏。 这意味着我将在后端和前端使用相同的语言。 这将是实时的,每个“房间”最多有20个人,所以我有几个想法:
-
我如何弥补所有用户之间的延迟,以便每个人都能同时看到相同的东西? 我想跟踪每个玩家的平均ping时间,find最慢的一个,并且通知其他客户端时间(以毫秒为单位),他们必须被延迟每个玩家,以便每个人尽可能地同步。
-
我正在考虑在后端和前端运行游戏代码(因为它的两端都是JavaScript),并且只是有一个错误纠正机制来与后端的“真实游戏”同步。 这样游戏在前端应该能够顺利执行,并且在同步发生时只有很less的毛刺。 此外,这将使前端JavaScript黑客最小化,因为作弊者将被同步到后端游戏。
-
我是否应该通过套接字(按键)接收玩家动作,通知所有其他玩家的动作,同时在后台“玩”游戏,并且每隔一次向整个游戏状态的每个人发送同步信息同时他们?
你怎么看? 有更多的东西我应该考虑或注意?
请发表任何想法或链接到多人游戏文件或文章。
编辑:这些是有用的:
- Gaffer on Games – Glenn Fiedler在多人游戏networking和物理方面的很好的文章
- Quake3networking模型
1 – 是不可能的。 您不知道邮件到达客户端需要多长时间,您所进行的任何测量都不一定适用于您发送的下一条邮件。 你可以做的最好的是一个近似值,但是你总是需要假设人们在稍微不同的时间会看到稍微不同的东西或者相同的东西。 我build议只发送当前状态给每个人,并使用内插/外推来平滑游戏玩法,这样每个人都可以在过去几毫秒的时间内看到游戏,而玩家之间和时间上的延迟都是不同的。 一般来说,这很less是一个大问题。 如果你真的想在服务器上caching一些以前的状态,你可以在它们之间进行插入,并将不同的旧数据发送给不同的人,以便同步他们所看到的内容,但是与传输时间的客户端模拟和抖动相结合,整个机器仍然会有一些差异。
2 – 典型的方法是在服务器上运行模拟,并将常规(小)状态更新发送到客户端。 客户通常运行自己的模拟,并有一种方法来混合他们自己的预测/内插状态和服务器正在发送的权威状态。 除了用户input之外的所有决定都应该在服务器端进行。 最终你融合这些的方式只是一个平滑的外观和一个准确的状态之间的权衡,所以这是一个美容决定,你将不得不作出。
3 – 您的客户通常应该将按键转换为逻辑操作。 您的服务器不关心密钥。 将该逻辑操作发送到服务器,并在需要时将其广播给其他客户端。 一般来说,虽然你不需要在这里做任何事情,但任何由行动引起的相关变化通常只会改变游戏状态,并因此将以该状态的正常广播发送出去。
我不会直接说出你的观点,因为其他答案performance的很好。 但是,我build议看一下HTML5,WebSockets和Comet,它们可以显着提高实时性能。 这些技术使您能够长时间运行HTTP请求,从而允许服务器将数据推送到客户端,而不是客户端轮询服务器。 这可以大大加快速度。
以下是一些应该certificate有用的资源:
- Wikipedia WebSockets条目
- 维基百科Comet条目
- 与Comet一起使用Node.js
- Node.js集成和更多信息
- Node.js,Comet和WebSockets上的幻灯片放映
- Socket.IO(Node.js WebSockets服务器和客户端的后备)
-
这个很难做,我可以看到很多同步到“最慢”的问题。 你可以放松一下,这样客户可以“最终一致”吗?
-
听起来不错。
-
我会把短的动作事件从前端发送到后端,让后端修改游戏状态并将游戏状态修改事件发回给客户端,并且只注意将必要的事件发送给正确的用户。 在这一点上,你可以放弃任何看起来不匹配或者看起来像假货/黑客的事件。
最好的方法是只跟踪一个地方的所有对象,即服务器。 每个人都会看到来自服务器的信息比“实际发生”晚一个旅行时间,而人们的命令将需要一次旅行才能在服务器上注册。 真的没有办法解决这个问题。 对于某些应用程序,可以立即模拟自己的移动而不用等待服务器响应,但是这无疑会导致计时编程的噩梦,人们通常会看到彼此“滞后”。 碰撞检测几乎是不可能的。
这样做的最终结果是,当你input命令后,直到你看到它们真的发生了,但是希望人们能够学会如何处理这个问题,并尝试稍微input一些命令来弥补。 慢速连接快节奏的实时游戏是不可能的。
如果你正在寻找一些示例代码来学习,那么在ActionScript中有一个在线的Pong多人游戏,服务器端的物理插件被客户端插入。
该Pong示例build立在联盟平台上 ,可以免费获得多达1000个同时连接的客户端。
Union有一个JavaScript客户端框架, OrbiterMicro(JavaScript客户端) 。
你也可以在JavaScript中编写你的服务器端逻辑,参见使用JavaScript创build房间模块 。
(充分披露:我是Union的联合创始人。)
一个典型的方法是不要试图强制所有的客户端运行在与服务器locking的同一个帧率上……它变得很难看。 相反,发送频繁的更新,以便客户端可以更新,每当他们收到新的更新。
通常情况下,客户端会预测短时间内的情况,然后通过服务器的更新进行纠正。 您也可以应用时间更正。 例如,如果服务器告诉你“玩家2正在以速度V行进”,那么你可以尝试通过最近的一次ping来知道这个消息有多大,并且纠正从P
到P + x*D
。
我回答了另外一个类似于这个问题的延迟问题,值得一读,同步到最慢的客户端可能不是最好的解决scheme,取决于游戏。
其他StackOverflow问题: 多人游戏移动同步