我正在使用java进行游戏并且进展顺利。我想尽早实现多人游戏,所以我建立在它上面而不是将整个游戏移植到多玩家时,它有很多不同的功能。 我想使它成为一个客户端/服务器应用程序。 现在我现在确定如何或如何实现多人游戏。我已经阅读了有关套接字和所有内容的java教程,我测试了它们并成功建立了连接(在测试项目中)。我不知道从哪里开始。我不知道如何转移例如不同的玩家在地图上的地方,或者甚至只是有任何玩家...我不知道是否使用图书馆或自己做什么或者做什么......如果有人可以请你给我一些关于如何通过TCP连接传输播放器数据或类似内容的指南,或者给我一个使其更简单的库..
答案 0 :(得分:5)
这是一个非常广泛的问题,有多种方法可以做,但这是我的看法。免责声明:我是移动多人游戏公司的服务器系统架构师。我不认为自己是这些事情的专家,但我确实有一些经验,因为我的工作和爱好(我写了我的第一个" MMORPG" 2004年支持了惊人的255名球员),并且觉得我可以把你朝正确的方向戳。对于这里的大多数概念,我仍然建议你使用谷歌,Stackoveflow等进行进一步的研究,这只是我的" 10000英尺的视图"游戏网络需要什么。
根据您正在制作的游戏类型(想想像第一人称射击游戏和像国际象棋这样的回合制游戏等实时游戏),底层传输层协议的选择非常重要。像Matzi建议的那样,UDP为您提供了更低的延迟(以及更低的数据包开销,因为标头小于TCP),但在不利方面,数据包到目的地的传递永远不会得到保证,即。您永远无法确定您发送的数据是否实际到达客户端,或者,如果您在一行中发送了多个数据包,则数据是否按正确顺序到达。您可以通过使用单独的消息确认到达的数据来实现可靠的UDP" - 协议(尽管同样,如果确认使用UDP,它们也可能丢失)并通过一些额外数据处理订单,但随后您(至少部分地)失去了较低的延迟和较低的开销。另一方面,TCP保证数据的传递并且订单保持正确,但由于数据包确认和开销(TCP数据包具有更大的报头)而具有更高的延迟。你可以说UDP数据包有点像#34;单独的实体",而TCP是一个连续的,不间断的流(你需要一些方法来区分一条消息的结束和另一条消息的开始)。
有两种游戏同时使用;单独的TCP连接,用于绝对必须进入客户端的重要数据,如玩家死亡等,以及另一个用于"火灾和忘记等的UDP连接。 - 类型的数据,如播放器的当前位置(如果位置没有到达另一个客户端,并且播放器正在移动,那么再次发送数据的意义不大,因为它可能是已经过时了,很快就会有另一次更新。
在为传输选择了UDP和/或TCP之后,您仍然可能需要一个自定义协议来对TCP / UDP数据包移动的数据进行编码和解码("有效负载")。对于游戏,显而易见的选择是一些binary protocol(与基于文本的协议,如HTTP)。简单的二进制协议可以例如标记消息中包含的总字节数,然后标记数据类型,数据字段长度和字段的实际数据(重复每个消息的字段数)。这可能有点棘手,所以至少对于初学者来说,你可以使用诸如序列化和反序列化你的消息对象之类的东西,然后查看现有的协议或自己烹饪(它真的不那么难)。当您获得基本数据类型(如字符串,整数,浮点数......)的编码和解码工作以及一些数据移动时,您需要设计自己的高级协议,这实际上是您的游戏和服务器的消息用来互相交谈。这些消息类似于"玩家加入游戏","玩家左游戏","玩家在这个位置,面对那里并以此速度移动这个方式" ,"玩家死亡","玩家发送了聊天消息"等
在实时游戏中,您还有其他一些挑战,例如预测播放器的位置(请记住,客户端发送的数据在到达其他玩家客户端时可能很容易在几百毫秒之前发送,因此您需要& #34;猜测"玩家到达时的位置)。尝试使用谷歌搜索#34;游戏航位推算"和#34;游戏网络预测" Gamasutra也有一篇非常好的文章:Dead Reckoning: Latency Hiding for Networked Games,可能还有很多其他的文章可以找到。
您需要考虑的另一件事是服务器端代码的并发性。许多人会告诉你,你需要使用Java NIO来实现良好的性能,并且每个连接使用线程都很糟糕,但实际上至少在Linux上使用Native Posix线程库(NPTL,几乎任何现代的linux发行版都会将它从方框),情况相反,供参考,见:Writing Java Multithreaded Servers - whats old is new。我们的服务器运行10k +线程,有数千个用户而不是窒息(当然,在任何给定时间,绝大多数线程都会休眠,等待客户端消息或消息发送给客户端)。
最后,您需要衡量游戏所需的计算能力和带宽。为此,您需要测量某个(服务器?)硬件可以对您的软件承担多少负载以及您的游戏导致的流量。这对于确定您可以使用服务器支持多少客户端以及您需要多快的网络连接(以及每月多少流量配额)非常重要。
希望这有助于回答您的一些问题。
答案 1 :(得分:3)
首先,多人游戏使用UDP进行数据传输。这有很多原因,例如较低的滞后等。如果您的游戏包含密集操作,并且需要快速反应,那么您应该选择基于UDP的内容。
可能有网上游戏的解决方案,但编写自己的实现也不是那么难。如果你有这个问题,你可能会在游戏的其他部分遇到问题。网上甚至是java都有非游戏导向的库和解决方案,但它们大多不是为游戏速度快而设计的。例如,远程过程调用可能包含昂贵的序列化并生成比您真正需要的更大的包。它们可以是方便的解决方案,但考虑到游戏而不是重新规划业务应用程序,性能较差。
例如,如果您有20个玩家,每个玩家都有坐标,状态,当然还有移动物体。你每秒至少需要20次更新,没有太多的延迟,这意味着很多流量。带有用户输入的20 * 20传入消息,以及包含大量信息的20 * 20传出消息。算一算。您必须尽可能地将所有播放器和尽可能多的对象数据压缩到一个包中,以获得最佳性能。这意味着您可能必须编写可以很容易地序列化为字节流的小数据包,并且它们必须只包含可行的信息。如果丢失了一些数据,这不是问题,但您需要处理重要信息以确保它们到达目的地。例如。你不希望玩家错过关于他们死亡的消息。
我在C#中编写了一个可靠且可用的网络“库”,这不是一项庞大的工作,但是建议环顾四周并将其构建得很好。这是关于这个主题的good article,请阅读它。即使您使用外部库,也可以掌握它正在做什么以及如何使用它。
答案 2 :(得分:0)
对于VM之间的通信,它不会比RMI简单得多。使用RMI,您可以在完全不同的计算机上调用对象上的方法。您可以将整个对象用作参数并返回值。因此,通知服务器您的移动可以像server.sendMove(someMoveObject, somePlayerObject, someOtherObject)
一样简单。
如果你正在寻找一个起点,这可能是个好点。