16

I'm creating my first online game using socket.io, and I'd like it to be a real-time multiplayer game like agar.io or diep.io.

But I've run into the issue of trying to figure out how to get all the computers to work at the same speed.

I have three ideas for models, but none of them seem right, and I'm wondering how normal videogames do it. (You can skip reading my ideas; they just give you a way to see the problems I'm having.)

  1. The server lets the clients run on their own and pass updates to the server, which then broadcasts them to the rest of the clients. This has the issue that some computers run faster than others, letting them update faster and move across the screen faster.

  2. Have the server tell the clients when to update. I can then wait until the last client responds (a terrible idea in case one person has a slow computer), wait until the first client responds (again, waiting for communication before each frame), or just send them as fast as possible (which seems to run into the same issue as number 1).

  3. At the beginning of the game, have the server tell the clients how quickly to update. This would mean the client would be responsible for restricting movement in between that time period. For example, if someone somehow managed to press a button twice within that time period, it would only send one button press event. This has the issue that some actions would be ignored (such as the double button press), and that the interaction would rely on the clock of the client, which might not match the clock of the server. The server would then have to keep track of each client and make sure their updates are being submitted at the correct time.

I've done some research, but the articles I read don't seem to specifically address what to do if a client sends updates faster than other clients.

In my particular case, I'm dealing with people who have faster keyboard speeds (their computer would send more keyboard updates than other computers).

How do programmers usually deal with this?

Pro Q
  • 667
  • 1
  • 7
  • 15
  • 1
    In my experience, they don't. This is why gamer machines exist; the ones who pay 5 grand for a state of the art flame thrower automatically have an advantage of the ones still using a Commodore 64. – Robert Harvey Jun 20 '16 at 17:55
  • 1
    So my game play is going to look slow because we have to play to the lowest-common denominator? Seems like the game server should set the tempo and it's up to the clients to keep up or you'll just have to lag. – JeffO Jun 20 '16 at 18:15
  • 3
    I may be misunderstanding the question, but using a tick based client and server model is probably what you're after. http://gamedev.stackexchange.com/questions/81608/what-is-a-tick-in-the-context-of-game-development Basically you just only process input and logic every X amount of time (usually 1/N seconds, such as 1/60 for 60Hz logic) – Christopher Wirt Jun 20 '16 at 18:32
  • 4
    After reading the question a bit closer, it seems that you're too focused on the client aspects of the game. If you want a "fair" multiplayer game, your server is going to have to be authoritative. Meaning that everything that happens to the clients is verified or done by the server. Then you restrict things from here, probably through a tick based system as above. – Christopher Wirt Jun 20 '16 at 18:35
  • @ChristopherWirt So "tick based" is basically the third option, right? The server tells the clients a certain speed to update at, and then broadcasts everything at that speed. My issue with that is that it seems some of the data would be lost if more than one thing happened in a tick. But then I suppose I could just stack those actions and send them on the next tick and apply some logic to figure out when stuff should stack and when it should not. (e.g. a held down button should not stack, but two clicks might) – Pro Q Jun 20 '16 at 18:52
  • @ProQ I'm not 100% sure, but I would guess that the client sends things much more abstract than something like a double click action, things that can be queued up to execute. If you had a game where a double click meant a specific action, you would have your client detect the double click and then send the associated action. If you're using javascript, there are ways (See: Jquery, among others) to process a click event only if it wasn't a double click. Then you send the actions according to input. The clients shouldn't be computing anything that the server isn't also doing, such as location. – Christopher Wirt Jun 20 '16 at 19:02
  • @ChristopherWirt sorry, I should have been more clear, both here and in my post. By a double click, I don't mean one action associated with a "double-click" I mean two separate actions dealing with two separate clicks. Like if someone hit the up button twice in a row within the tick time; the unit should move up twice, once in the first tick and once in the next tick. Whereas if they hold the button, they should only move until the button is let go (the large number of triggered button presses from them holding it should not cause them to move forever). – Pro Q Jun 20 '16 at 19:21
  • I'm going to make an answer to outline my thoughts on the subject a bit more clearly. – Christopher Wirt Jun 20 '16 at 19:27
  • 1
    Ah, real-time netcode. The Deepest, darkest place of game development. Welcome to the ship, mate! – T. Sar Jun 20 '16 at 19:42
  • Hey, just keep in mind - ticks in real-time netcode are usually on the 50ms window for high-performance, high-responsiveness games, like shooters. Very few people can issue commands to a computer on that speed! – T. Sar Jun 20 '16 at 20:11
  • There's really no issue here. The clients can send updates the the server as often as they want - and you can't control it anyhow, since you can't really control the network itself. The server will send out updates at its own rate to all the clients at the same time and they will update their game state (and therefor rendered graphics) as quickly as they can once they get an update. The server "ticks" by computing updated legal game state using the most up to date client data available. There's no need to do anything fancy for a client/server architecture. Lock-step p2p is different. – xaxxon Jun 21 '16 at 07:23
  • you are thinking something really wrong. In an online game the bottleneck of performances is not the keyboard speed but the bandwidth. – JoulinRouge Jun 21 '16 at 07:30
  • @JoulinRouge Since I'm new to programming games, they both present the same problem to me. If the keyboard is set to give more input in the same amount of time, it would create the same advantage as a computer that had a faster communication with the server. – Pro Q Jun 21 '16 at 14:17

3 Answers3

8

Your third idea seems to be the closest to what I think of as the industry solution to this sort of problem.

What you're describing is commonly referred to as Ticks. In each tick, a fixed number of actions would be processed for each client in serial. Often times, game servers will have some parallel actions when capable, but this is a much more complicated problem.

A tick is likely going to be in the form of 1/N seconds, N being the number of ticks per second, or Tickrate. This tickrate could be very very often or very infrequent, depending on your use-case. My personal suggestion would be to avoid a tickrate above 60 ticks/second unless you are sure you need more. You probably don't :)

Actions should be atomic. For example, in slither.io, an action such as moving should not immediately process something like breaking your chain, unless the player you hit has already taken their move. This may seem trivial for something on the level of pixels, but if you're dealing with tile-based movement, it becomes much more obvious, and ensures fairness. If Player A moves to tile X,Y and Player B is currently on that tile, you must ensure that by the end of the tick, player B will still be on that tile for any actions to take place between them.

Further, I'd say avoid having any of your calculations done on the client side unless they are independently done on the server side. This gets complicated and expensive with physics (many games opt for a lower tick-rate for physics than many other actions and events because of this)

For reference, here is a good link to supplement your own understanding of game servers and multiplayer networking.

Lastly, I'd say don't let fairness ruin your server. If there are exploits that cause your game to be unfair, fix those. If it's a matter of a better computer having slight advantage, I'd say it may not be as big of a deal.

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
  • 3
    @ProQ it's worth to note that writing good netcode isn't trivial! If your app doesn't work nicely from the start and your netcode seems to suck, don't give up. Even people that do that for a living everyday have issues with it. it is just _that_ hard! – T. Sar Jun 20 '16 at 20:40
0

The following system makes sure all clients and the server share almost the same game state at any time.

Have the state of the game on both client and server.

When a client tries to use a command (mouse, keyboard, etc other input), look on its state of the game if it is valid.

If it is , send the command to the server, without executing it on the sending client.

When the server receives the command, look on its state of the game if it is valid.

If it is, send the command back to ALL clients with the exact future date after what it should be finished being executed on the server, then execute the actions requested by the command after a delay equal to the minimum time to send the command to clients. then record the date, this helps make future prediction. If the time varies too much, make your game system more time deterministic.

When a client receives a command from the server, look on its state of the game if it is valid immediately execute the actions requested by the command, then look at the the current date and compare it to the date prediction received. If it is not valid the client is out of sync. (All clients with a similar connection receive at the same time)

If the date is before, you got a problem in the previous step, fix that. If the date is slightly after do nothing, If the date is long after, the client is out of sync, i.e. the client lags behind too much.

When a client is out of sync, request a copy of the entire game state of the server, and use that one. If that happens too often, fix that because it is more expensive than sending commands.

On the clients, render stuff on screen ONLY when there is nothing else left to do. In simple scenarios the render function takes only current game state as input.

On top of that you can optimize alot, by using predictive systems, grouping commands, render only diffs etc...

Validation should differ, for instance, it's up to the server to limit the command requests / time unit.

0

I don't know if this is problem of libraries or environment you are using, but I think you are approaching it totally wrong.

In massive majority of multiplayer games, it is only server that is doing any real calculations. Clients are only dumb IO machines where only real performance problem is drawing 3D graphics. And it that case it doesn't matter if client can run at 20 or 200 FPS, because that only affect visuals. That means "client update" has absolutely no meaning. Client might try to "predict" what server might calculate, but that is only to smooth out the feeling of gameplay and has no actual impact on gameplay itself.

faster keyboard speeds

I don't even know what that means. Most people can't even keep up with speed of low-end keyboards, so how would that affect the performance of players?

Otherwise, the question seems quite too broad and you should instead focus on single actual problem, instead of trying to make up "general" problem that you might not even have.

Euphoric
  • 36,735
  • 6
  • 78
  • 110
  • faster keyboard speeds isn't about typing, its about how many commands can be sent if you hold down the "move forward" key or the "shoot" key. – gbjbaanb Jun 21 '16 at 07:26
  • @gbjbaanb And how is that a problem? You should only care about pressed and released commands. You should not care about how fast the update it. – Euphoric Jun 21 '16 at 07:29
  • You care if you were handling all events like the OP expected - on the client So if pressing w made you go forward a little distance, and your keyboard was faster than someone else's you'd go faster than them. Last thing you want is to make a racing game you had to keep pressing a key to move forward! – gbjbaanb Jun 21 '16 at 09:32
  • @gbjbaanb No. That is wrong. The server knows "player is going forward" and then every 1/60th of the second it updates positions of ALL players based on if they are going forward. This is how ALL games work. The update loop is same for all entities in game and updates ARE NOT based on events from UI. – Euphoric Jun 21 '16 at 10:01
  • 1
    No, that's not what the OP's understanding was, which is why he asked it, and which is why you said "I don't even know what that means". If you understand the OPs position, then his question makes sense. If the OP has coded his game to work with a game loop based entirely on how fast events are delivered from the client then that's what he is asking about - you are wrong to apply some hypothetical game design to what the OP is actually asking about, regardless of whether his design is wrong by most standards. – gbjbaanb Jun 21 '16 at 10:09
  • @Euphoric, gbjbaanb is right on. Thanks both of you for having this conversation. Hopefully it will allow people to understand my question better. – Pro Q Jun 21 '16 at 14:30
  • @ProQ There are reasons why your approach is not used in real games. This being one of them. You should just start again and properly this time. – Euphoric Jun 21 '16 at 14:31