使多人游戏可通过网络或互联网玩

2022-09-02 23:06:24

嗨,我用Java写了一个多人游戏,我想知道我需要学习什么和/或我应该使用什么才能使游戏可以通过网络或互联网通过多台计算机玩。我真的不知道从哪里开始,所以任何建议都会有所帮助,谢谢。


答案 1

这些其他答案都是相当高级的,这很好,但你不想要高级,你想要低级,就像“我如何让它实际发送数据,这意味着什么,我发送什么,等等。以下是您要执行的操作:

首先,TCP还是UDP?如果您不知道这两件事是什么,请阅读它们,因为我没有空间在这里对两者进行很好的概述,但是对于您的选择,请了解以下内容:

  1. TCP适用于回合制游戏或通常可以高延迟的游戏,因为TCP保证数据包传递,因此可能需要一些时间才能重新传递丢弃的数据包。这对于国际象棋或其他任何轮流的东西都有好处。
  2. UDP适用于您不一定关心消息可靠性的游戏,并且希望数据继续发送,如果您错过了某些内容,哦,好吧。这适用于基于实时动作的游戏,例如HALO:Reach或Call of Duty。在这些情况下,如果你发送一个对象的位置,而对象永远不会到达那里,那么发送一个新位置比重新发送一个旧位置(现在甚至更旧)更好,所以一直保证可靠性并不重要。也就是说,您必须使某些内容100%可靠,因此您仍然需要某些内容来保证交付,例如对象创建和对象销毁。这意味着您需要在UDP之上实现自己的半可靠,基于优先级的协议。这很困难。

因此,问问自己什么是重要的,了解TCP和UDP的工作原理,然后做出明智的选择。

也就是说,现在您必须通过网络同步对象状态。这意味着您的对象需要序列化为可以在字节流中表示并写入套接字的内容。写入套接字很容易;如果你能写到一个文件,你可以写到一个套接字,这真的不难。重要的是要确保你能够将一个对象表示为缓冲区,所以如果你的对象有指向其他对象的引用/指针,你将无法只发送这些指针,因为它们在其他客户端上是不同的,所以你必须将它们转换为所有主机通用的东西。这意味着 ID,尽管对象的 ID 在所有主机中必须是唯一的,因此您必须有一种方法在主机之间进行协调,以便没有两个主机会创建具有相同 ID 的不同对象。有一些方法可以处理主机执行此操作,但我们在这里不会担心(提示:在主机的ID和网络ID之间使用某种映射。更大的提示:如果你不需要,不要这样做)。

所以现在你可以发送数据了,太好了,现在该怎么办?每次游戏状态更改时,您都必须以某种方式向其他计算机发送更新。这就是客户端-服务器体系结构的用武之地,或者如果需要,也可以进行对等。客户端-服务器更易于实现。此外,一个主机“充当”服务器仍然是客户端 - 服务器,任何说不同的人都是错误的。

因此,服务器的责任是“拥有”所有游戏状态。只有服务器才能明确说明对象处于什么状态。如果你想移动一个对象,你告诉服务器你想移动,但是服务器然后告诉你你应该移动对象,你不只是这样做(尽管某种客户端预测通常是有用的)。服务器将更新后的对象状态发送到所有其他主机。

所以,你提到了回合制游戏,对吧?非常简单:

  1. 您将解决当前轮到它的客户端的完全打开问题。一旦该客户端执行了他们想要执行的操作,请将该轮次的结果发送到服务器。然后,服务器验证客户端的移动(不要只信任客户端,作弊以这种方式发生),并将它们应用于其对象状态。
  2. 服务器处于最新状态后,它会向具有新世界状态的所有其他客户端发送消息,这些客户端将应用这些更新。这包括刚刚轮到他们的客户;该客户端应该只在服务器告诉它时才更新其世界状态,因为您希望确保与其他主机的一致性,并且您希望防止主机作弊。
  3. 然后,服务器发出一条消息,指示轮到谁。您可以在上一步中的世界状态更新的同时发送此消息,这很好。只要注意客户试图使他们的投票失去秩序。这就是为什么服务器对世界具有权威性的原因;如果客户端试图作弊,服务器可能会将其击倒。

这就是回合制游戏需要做的所有事情。提示:使用TCP更大的提示:TCP实现了一种称为“Nagle算法”的东西,它将你的消息组合成一个数据包。这意味着,如果您发送两条单独的消息,并对“发送”进行两次单独的调用,则其他主机可能会在一次调用“Receive”时仅接收一个数据包,但该数据包将包含已发送的两个数据包的内容。因此,如果您发送两个 100 字节数据包,同时发送两个要发送的调用,则可能会在单个调用上接收一个 200 字节数据包。这是正常的,所以你需要能够以某种方式处理这个问题。一个技巧是使每个数据包的大小相同,然后每次检查输入时从套接字中读取那么多字节。还要记住,您也可能收到部分消息。例如,如果发送两条 100 字节的消息,则可以将它们合并为一条 200 字节的消息。接下来,如果从另一端的套接字读取,但读取的缓冲区大小为 150 字节,则将有 150 个字节,其中包含第一个数据包和第二个数据包的一部分。您必须拨打第二个电话才能接收第二条消息的其余部分,因此请跟踪您收到的数据量,以免在某个地方错过数据包的一部分。这就是为什么保持数据包大小相同非常有用的原因。

还有许多其他有用的技巧可以减少消息的大小和频率,并跟踪不是回合制游戏并实时行动,但是如果您有回合制游戏,那么正确的做法可能是使用TCP而不必担心任何其他事情。以下是一些指向有用网站和文章的链接,这些网站和文章将为您提供有关如何完成游戏网络编程的更多信息:

  • Glenn Fiedler的网站,这里有一些很棒的信息。
  • 1500个弓箭手,一篇关于如何实现一种称为确定性锁步的技术的好论文,该技术对许多类型的游戏都很有用。

如果您想了解有关任何此类内容的更多详细信息,或者您有更具体的问题,请告诉我。


答案 2

一种可能的架构方法是让游戏的一个实例充当主机(例如,第一个启动的实例)。它将协调游戏,并将游戏状态和回合的信息发送给其他每个玩家。

当玩家进行移动时,它会将移动信息发送到主机,主机将更新游戏的状态(并检查移动的有效性等)。然后,它会将新的游戏状态发送给每个玩家,并将下一回合的通知发送(可能作为单独的通信)到相应的客户端并等待其响应。

从某种意义上说,主机在此方案中充当游戏服务器,但使用/玩起来可能更简单,因为没有必须运行单独的进程才能玩游戏。


推荐