📜 ⬆️ ⬇️

Protocol features in IO games

Suppose you want to create an IO game. Something like agar.io, slither.io and thousands of them .

What is an IO game?
This name was assigned to the browser, client-server multiplayer games in real time.

The mechanics of such games are usually relatively simple and interest is achieved through epic battles between a large number of real players.
')
The ancestor of the genre is agar.io

Many people know that in these games use websocket. And there is nothing difficult in creating your own protocol above it. I thought so when about a year ago we started a space shooter project in this style.

Now I do not think so.

What is the problem


The main problem that all multiplayer game developers have to solve is achieving the “simultaneity” of what is happening.

Naive approach: let me move my hero, send these movements to the server, and the server will send them to my opponents - does not work. If you do this, then your hero will live in real time, and his rivals in the past. Their movements will lag about two pings to the server. Let's say if ping is 100ms, then you will see where the rivals were 200ms ago. Accordingly, it will be impossible to play.

Formulation of the problem


There are two-dimensional rooms in which flying, following the mouse pointer, space ships.
You need to create a protocol so that:


Disclaimer:

The final result is very simple.

But try, for the purity of the experiment, to come up with your own version before reading the article, in order to avoid the effect of retroactive knowledge when writing comments.

First decision


Let each client, when drawing each frame, send the position of the mouse cursor to the server.
And the server, having received it, immediately reads the current coordinates of the ship and sends them to all clients (including the one who transmitted the coordinates of the mouse).

It's simple. Simultaneity is achieved here.

And it even works while we have a server locally, and very few clients.

Under the conditions close to real, such an approach gave three things: rabid traffic (which exceeded the traffic of agar.io by an order of magnitude), periodic “jumps” of ships (instead of a smooth flight) and wild lags, which usually began in 3-5 minutes, and then they never went through and were “treated” only by restarting the browser.

The second version of the protocol


The first edit was obvious: it was wrong to send ship transfers immediately after receiving a management team from a client.

If you do this, then the frequency of the arrival of commands from the server to clients depends on three things:


Too many variables. Measurements showed that commands that, in theory, are sent every 20 ms, arrive at a random interval from 5 to 90 ms.

The solution to this problem was simple - instead of sending the command to the client immediately, they made a timer sending - one command in 20ms.

"Jumping" ships have decreased significantly ...

Third version


... but not disappeared.

At some point, obeying the network lags, the next packet came with a big delay. Not after 20ms, but after 100, for example.

Accordingly, the ship first braked, and then abruptly darting off and "teleported" a few pixels.

And then a strange idea arose: and in the case of such delays, let us move the ship in the same direction, to which it flew earlier.

Maybe the picture will become smoother? This idea did not work, but it turned out to be a step towards the right decision.

And so, the ship on the client now all the time (that is, every frame) flies with its constant speed.

Commands to change this speed come from the server, as well as “corrections” for the coordinates of the ship.

Result? Instead of rare long-distance jumps, our ships began to make a series of jumps for short distances.

It turned out that from the point of view of the client the ship is in one place, and from the point of view of the server - in another.

“Corrections” sent from the server and led to microjumps.

Further can serve as an example, as two moronic not entirely successful ideas, implemented consistently, can give an unexpected result:

And let's send the amendment less often and see what happens!

Nothing good, of course, did not work - the jumps again became more rare and long.
But on the other hand, I noticed that the control of the ship does not become less responsive even with a multiple increase in the interval between the sending of the amendment.

Fourth version


But this means that I absolutely in vain mixed two characteristic quantities: FPS - the need to move the ship on the screen 60 times per second, and sending a control signal from the mouse.

The control signal can be sent much less frequently, since it correlates not with the peculiarities of human vision, but with the speed of human reaction.

And she - about 200-250ms!

Taking into account the ping to the server (approximately 100 ms), this meant that the control signals can be sent about once every 100–150 ms, and the smoothness of movement is already provided on the client.

As a result, the fourth version of the protocol looked like this:


Bonus from this version - a sharp decrease in traffic. Now he has become the same as on agar (it seems that Matheus Valadares knew something!).

But the most important thing is that the problem of heavy lags, occurring in 3-5 minutes and incurable by nothing, was automatically solved.

(A few days later I came across this article and it became clear exactly what was happening there).

Now there was only one problem - small jumps of the ships during synchronization.

Version five - final


If synchronization is not done or is rarely done, then the location of the ships on the server and on the clients turned out to be different, which naturally was unacceptable.

But we also did not want to endure jumps that turned into really full-fledged jumps at any network delay.

The original idea looked like this: What if we "spread" time synchronization? Here we will not immediately move the ship to the desired point, but tell it to move there frames for 7-8?

“So, but this is an additional delay ...”
- And by the way, we change the speed of the ship only once every 120ms. So we know in advance where it will be after 120ms!
- From this place more!

Thus, the simplest (when retroactively considered) idea was born: instead of synchronization, the server sends to the client the coordinates of the ship where it should be in 120ms.

And the whole protocol became so:


This protocol solved all the problems. It is resistant to packet delays.

Even if for some reason the ship did not reach (or flew) the former one at the moment of receiving a new target, this will not affect the smoothness of the course in any way - only the speed will be slightly corrected.

Now we are pleased with the protocol. The result can be seen here: https://spacewar.io

Source: https://habr.com/ru/post/323466/


All Articles