制作可通过网络或互联网玩的多人游戏

发布于 2024-11-05 15:06:51 字数 99 浏览 0 评论 0原文

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

Hi I've written a multi-player game in Java and I was wondering what I need to learn and/or what I should use in order to make the game playable over a network or on the internet by multiple computers. I'm really kind of clueless as to where to start so any advice would be helpful, thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

奢望 2024-11-12 15:06:51

这些其他答案都是相当高级的,这很好,但是你不需要高级,你想要低级,例如“我如何让它真正发送数据,这意味着什么以及我该怎么做”发送等”您需要执行以下操作:

首先,选择 TCP 还是 UDP?如果您不知道其中任何一个是什么,请阅读它们,因为我没有足够的空间在这里对两者进行详细介绍,但为了您的选择,请了解以下内容:

  1. TCP 适用于回合制游戏或游戏高延迟通常是可以接受的,因为 TCP 保证数据包传送,因此可能需要一些时间才能重新传送丢弃的数据包。这对于国际象棋或其他轮流进行的游戏很有用。
  2. UDP 非常适合游戏,在这些游戏中,您不一定关心消息的可靠性,并且希望数据不断发送,如果您错过了某些内容,哦,好吧。这对于基于实时动作的游戏很有用,例如《光环:致远星》或《使命召唤》。在这些情况下,如果您发送一个对象的位置,而该对象永远不会到达那里,那么发送一个新位置比重新发送一个旧位置(现在更旧)更好,因此始终保证可靠性并不重要。也就是说,您必须让某些事情 100% 可靠,因此您仍然需要某些事情来保证交付,例如对象创建和对象销毁。这意味着您需要在 UDP 之上实现您自己的半可靠、基于优先级的协议。这很难。

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

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

现在您可以发送数据了,太好了,现在怎么办?每次游戏状态发生变化时,您都必须以某种方式向其他机器发送更新。这就是客户端-服务器架构的用武之地,如果你愿意的话,也可以是点对点架构。客户端-服务器更容易实现。此外,一台“充当”服务器的主机仍然是客户端-服务器,任何不同的说法都是错误的。

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

那么,您提到了回合制游戏,对吗?非常简单:

  1. 您将解决当前轮到的客户的完整轮次。一旦该客户端完成了他们想做的事情,就将该轮的结果发送到服务器。然后,服务器验证客户端的动作(不要仅仅信任客户端,作弊会以这种方式发生)并将其应用到其对象状态。
  2. 一旦服务器更新,它就会向所有其他客户端发送包含新世界状态的消息,然后这些客户端应用这些更新。这包括刚刚轮到的客户;该客户端应该仅在服务器告诉它时更新其世界状态,因为您希望确保与其余主机的一致性并且希望防止主机作弊。
  3. 然后服务器发出一条消息,指示轮到谁了。您可以在上一步中更新世界状态的同时发送此信息,这样就可以了。请注意客户试图打乱顺序。这就是为什么服务器拥有全世界的权限;如果客户端试图作弊,服务器可以将他们打倒。

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

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

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

Those other answers are both fairly high-level, which is fine, but you don't want high-level, you want low-level, as in "how do I make it actually send data and what does that mean and what do I send , etc." Here's what you do:

First, TCP or UDP? If you don't know what either of those things are, read up on them as I don't have space to give a good rundown on both here, but for your choice know the following:

  1. TCP is good for turn based games or games where high latency is generally ok, since TCP guarantees packet delivery so it's possible that it could take some time for a dropped packet to be re-delivered. This is good for things like Chess, or anything else that takes turns.
  2. UDP is good for games where you don't necessarily care about reliability in messages and would prefer that data just keeps sending and if you miss something, oh well. This is good for games that are real-time action based games, such as HALO:Reach or Call of Duty. In those, if you send an object's position, and the object never gets there, it's better to send a new position than to re-send an old position (which is now even older) so it's not important to guarantee reliability all the time. That said, you MUST have certain things be 100% reliable, so you'll still need certain things to guarantee delivery, such as object creation and object destruction. This means you need to implement your own semi-reliable, priority based protocol on top of UDP. This is difficult.

So, ask yourself what is important, learn how TCP and UDP work, and then make an intelligent choice.

That said, now you have to synchronize object state across the network. This means that your objects need to serialize to something that can be represented in a byte stream and written to a socket. Writing to a socket is easy; if you can write to a file you can write to a socket, it's really not hard. What's important is to make sure that you are able to represent an object as a buffer, so if your object has references/pointers to other objects, you won't be able to just send those pointers since they're different on the other clients, so you have to convert them to something that is common to all the hosts. This means ID's, although an object's ID must be unique across all hosts, so you have to have a way to coordinate between hosts such that no two hosts will create different objects with the same ID. There are ways to handle hosts doing this, but we won't worry about that here (hint: use some sort of mapping between the host's ID and the network ID. Bigger hint: Don't do this if you don't need to).

So now you can send data, great, now what? Every time the game state changes, you must send an update to the other machines somehow. This is where the client-server architecture comes in, or peer-to-peer if you want. Client-Server is easier to implement. Also, one host "acting" as the server is still Client-Server and anyone who says differently is wrong.

So, the server's responsibility is to "own" all game state. Only the server can definitively say what state an object is in. If you want to move an object, you tell the server that you would like to move, however the server then tells you that you should move the object, you don't just do it (although some sort of client-side prediction is often useful). THen the server sends the updated object state out to all the other hosts.

So, you mentioned a turn-based game, right? Very simple:

  1. You're going to resolve a full turn on the client who's turn it currently is. Once that client does what they want to do, send the results of that turn to the server. The server then validates the client's moves (don't just trust the client, cheating happens that way) and applies them to its object state.
  2. Once the server is up to date, it sends messages to every other client with the new state of the world, and those clients apply those updates. This includes the client that just took their turn; that client should only update its world state when the server tells it to, since you want to ensure consistency with the rest of the hosts AND you want to prevent a host from cheating.
  3. The server then sends out a message indicating whose turn it is. You could send this at the same time as the world state update in the previous step, that would be fine. Just be aware of clients attempting to take their turn out of order. That's why the server has authority over the world; if a client tries to cheat, the server can smack them down.

That's all you'll need to do for a turn-based game. Hint: Use TCP
Bigger hint: TCP implements something called "Nagle's Algorithm" which will combine your messages into a single packet. What this means is that if you send two separate messages with two separate calls to "Send", it's possible that the other hosts will receive only one packet on a single call to "Receive" but that packet will contain the contents of BOTH of the packets that were sent. Thus if you send two 100-byte packets with two calls to send, you may get one 200-byte packet on a single call to receive. This is normal, so you need to be able to deal with this somehow. One trick is to make every single packet the same size, and then just read that many bytes from the socket every time you check for input. Keep in mind also that you could get partial messages as well. For example, if you send two 100-byte messages, they can be combined into a single 200 byte message. Next, if you read from the socket on the other end, but you read with a buffer size of 150 bytes, you'll have 150-bytes, which contains the first packet and part of the second. You'll have to make a second call to receive to get the rest of the second message, so KEEP TRACK OF HOW MUCH DATA YOU'VE RECEIVED so that you don't miss part of a packet somewhere. This is why keeping your packets the same size is useful.

There are a number of other useful tricks for reducing the size and frequency of your messages and for keeping track of games that are not turn-based and act in real time, but if you have a turn-based game, then the correct thing to do is probably use TCP and not worry about any of that other stuff. Here are some links to useful websites and articles that will give you more information on how game network programming is done:

  • Glenn Fiedler's site, some great info here.
  • 1500 archers, A great paper on how to implement a technique called deterministic lockstep, which is useful for many types of games.

Let me know if you want more details on any of this stuff or if you have more specific questions.

窝囊感情。 2024-11-12 15:06:51

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

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

从某种意义上说,主机在这种情况下充当游戏服务器,但可能更容易使用/玩,因为没有必须运行才能玩游戏的单独进程。

One possible architectural approach would be to have one instance of the game act as the host (e.g., the first one to start). It would coordinate the game and send information of the game state and turns to each of the other players.

When a player makes a move, it would send the move information to the host, which would update the state of the game (and check for validity of the move, etc.). It would then send the new game state to each of the players and also send (likely as a separate communication) notification of the next turn to the appropriate client and await its response.

In some sense, the host acts as the game server in this scenario, but may be simpler to use/play in that there is not a separate process that must be run in order to play the game.

你穿错了嫁妆 2024-11-12 15:06:51

如果您想通过网络添加多人游戏功能,请查看 Netty 项目< /a> 构建通信基础设施。

但在此之前,您需要确保您的游戏具有正确的“架构”。您需要大型模块:客户端和服务器。

服务器负责所有游戏逻辑。从某种意义上来说,它就是游戏引擎。客户端负责向服务器查询游戏状态,将其显示给玩家,获取玩家输入并向服务器发送命令。

一种解耦客户端和服务器代码而不需要学习网络编程的麻烦的方法是让两个不同的程序从 CLI 运行。执行顺序可以是这样的:

  1. 运行服务器来初始化游戏状态,游戏状态保存在文件中。
  2. 客户端运行,它读取游戏状态,以某种方式显示它并从玩家那里获取一些输入。它将输入保存到文件中。
  3. 服务器运行,它从客户端读取命令,更改游戏状态并更新状态文件。

冲洗并重复。这基本上就是 PBEM 服务器所做的事情。

为了帮助解耦客户端和服务器,定义一种“语言”来表示游戏状态的变化以及服务器要执行的命令是有意义的。如果客户端缓存状态并应用从服务器发送的更改,则会有所帮助。

一旦您的客户端和服务器代码完全解耦,并且“语言”被完全定义,您就可以将通信机制从基于文件更改为基于套接字。

If you want to add the multiplayer feature over the network, it may be useful to you to take a look at the Netty project to build the communication infrastructure.

But before you can do that, you need to make sure that your game has the right "architecture". You need to have to big modules: the Client and the Server.

The Server is responsible for all the game logic. In a sense, it is the game engine. The Client is responsible to query the Server for the game state, display it to the player, get the player input and sending commands to the server.

One way to decouple our Client and Server code without the hassle involved in learning network programming is to have two different programs that run from the CLI. The sequence of execution can be like this:

  1. The server is run to initialize the game state, the game state is saved in a file.
  2. The client is run, it reads the game state, display it somehow and gets some input from the player. It saves that input to a file.
  3. The server is run, it reads the commands from the client, changes the state of the game and updates the state file.

Rinse and repeat. This is basically what PBEM servers do.

To help decouple the Client and the Server, it makes sense to define a "language" to represent changes in the state of the game, and the commands to be executed by the server. It helps if the client caches the state and apply the changes as sent from the server.

Once your Client and Server code is completely decoupled, and the "language" is completely defined, you're ready to change the communication mechanism from being file-based to being socket-based.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文