Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a multi-player game playable over a network or on the internet

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.

like image 368
Bob Anderson Avatar asked May 09 '11 14:05

Bob Anderson


People also ask

Can you make a multiplayer game without a server?

If you're building a game that's mostly player-to-player interaction, without a ranked competitive system, you may not need servers at all. For example, Minecraft does this particularly well. You can play by yourself, on a local network, connect to servers hosted by other players, or host your own server.

Which type of networks enabled the first multi player games?

The real revolution in gaming came when LAN networks, and later the Internet, opened up multiplayer gaming. Multiplayer gaming took the gaming community to a new level because it allowed fans to compete and interact from different computers, which improved the social aspect of gaming.


1 Answers

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.

like image 87
Jeff Tucker Avatar answered Oct 05 '22 23:10

Jeff Tucker