PlayerIO

The fastest way to build online games without breaking a sweat.

Building Flash Multiplayer Games

This tutorial is also available in a pure flash version..

Table of contents
1 - Introduction 8 - Synchronization
2 - Game Basics 9 - Interpolation
3 - Turn Based Games 10 - Latency
4 - Network Architectures 11 - Tips & Tricks
5 - Security 12 - Game: Turn Based
6 - Example Game 13 - Game: Realtime uninterpolated
7 - Real Time Games 14 - Game: Realtime interpolated

Dealing with latency

Our problems

Even if we can synchronize perfectly and have what shows up on our screen be a perfect representation of what is actually happening, we still have a significant and unavoidable time lapse between what we see and what actually happens.

No matter what we do, we cannot get rid of this time lapse due to latency. As such, we must work around it instead so that our game is fair and our players do not leave us to play something that handles this problem with more success.

Let us look again at the fatal decision that troubled us not too many chapters ago. Did player 2 hit player 1?

With the setup we have currently, this problem cannot be avoided. But not all hope is lost. If we think about what we really want out of this decision, a solution begins to form. Our list of desires is: We want both players to be happy, we want the game to seem fair and we want to reward the player who plays well. So, the decision becomes evident to give player 2 the hit. They played well and hit the target they saw on their screen.

But what about player 1?

We cheat

Of course we care about what player 1 sees and what he thinks of this decision. He thinks the decision is terrible! We have not accomplished all our objectives yet. We need to make player 1 happy and make the game seem fair.

If you hadn't noticed the wording yet, we make it SEEM fair. Regardless of what he should have actually seen, wouldn't it SEEM fair if player 1 saw this when he got hit?

All we've done here is modify player 1's view so that he sees himself get hit. We already decided that player 2 hit player 1 before we sent the message out to player 1. Why should player 1 see something that didn't happen?

Again, the most important thing you can ever have in a real-time game is the illusion that everything is working smoothly and that there are no possible sources of problems. If you create a smooth real time engine, you are just as qualified to be a master magician as you are to be a programmer.

Of course, this isn't the only solution to latency. There are other solutions that are more down to earth (but they have large weak points). In addition, we are not quite done with this solution yet. there are still problems we must address.

For example, corners give us big problems.

Player 2 shoots at player 1 just as he goes into hiding behind a wall. This looks okay from player 2's perspective. He gets a solid hit and all is good and done.

Right?

Let's look at this from player 1's perspective.

Player 1 sees himself as farther ahead then player 2 sees him. this means that he is well behind the wall by the time he sees player 2 fire.

In this situation, we can't even fake player 2 hitting player 1. We can't cheat our way out of all situations. Thankfully, players notice these errors less then you would think. Just about every major FPS suffers from this error. I'm sure you can think of times you got killed while running around a corner to safety. You likely thought that you died before you got to safety and only fell behind cover as your body went limp and died.

This is actually an important point. Although these latency errors appear large when we look at freeze frames, really these errors only occur over fractions of  a second. By the time a player recognizes something might be wrong, it's all over and they can only guess what they actually saw.

If the player has a good ping (less then 100) then any discrepancy will be over in a 10th of a second and if they trust your game to be smooth and lagless, they will give you the benefit of the doubt and believe what the game tells them happened. Note that this again relies on our master deception. The appearance of a seamless game... NEVER let this go.

Of course, if the player has bad ping (something like 300ms), they will see these errors as bright as day. To combat this, we need to either use a technique that prevents these contradictions, kick players with an unmanageable ping or ignore those with terrible connections let them suffer the reduced experience.

But still there is more to solve..

We have to determine if the player who is shooting actually hit anyone. This is harder then it sounds. Remember our section on security? We can't trust that player to tell us if they hit or not. They could lie and tell us they hit every time!

But as the server, we don't know exactly what any single player sees on their screen at any one moment. There is latency between the server and client.

We approximate! By keeping track of the ping we know how far behind that player's screen is. Using this information we can reconstruct what that player should be seeing at this very moment.

Of course a variable ping or bad synchronization can make this technique crash and burn badly. Overall, however, it performs well. (It is used in a multitude of major  games and is applicable to any variety of scenarios)

A solid solution

Of course, our solution thus far is still all just smoke and mirrors. Thankfully, we can in fact achieve a more robust engine but it will come at a severe cost. One that you will likely not want to pay for any real time games and most assuredly not for a "twitch" game.

Recall the setup we had when we were making turn-based games? we would send a message to the server then wait for a reply, We would not move or do anything else. We would not predict out position. As it turns out, prediction is the root cause behind most of these problems. We have been trying to let the player move immediately when in reality he hasn't moved yet.

The solution is easy. Don't. Don't move the player until the server tells you to.

As far as easy fixes go, this one REALLY takes the cake. Just... treat your own player like any other player. Follow the server's instructions to the word and ignore player input until the server tells you that it has occurred.

By doing this, we remove all and every problem caused by differing player screens. You can be essentially guaranteed that all players see the same thing now! (albeit, at different times due to different latencies!)

When the server sends out it's updates, you get updates about your player at the same time as other players so you are acting on the same information.

But wasn't there a catch?

Everything seems fine and dandy until you try and play. Suddenly your movements have gotten sloppy and disjoint. You have to wait before your character begins to move! Even worse, you have a time delay before your character stops moving! This makes it easy for the unwary or unlucky player to walk straight to their death when they're not even holding down keys. Even worse, the time delay isn't constant, making it impossible to judge when to release a key or get a good feel for it. Even worse, this delay could easily be 300 ms for the average player playing a flash game with a bad connection.

In other words, if you use this for something time-critical such as movement your players will probably hate you. It is better suited for less time-critical application such as general RTS usage.

But who said the master magician couldn't work his magic even when he has a solid system to work with? We can still attack with smoke and mirrors! Only this time we aren't tweaking player positions or using sleight of hand to cover up mistakes. Instead, we are going to look at the game design itself!

An almost identical game with slight tweaks in the design may be all that you need to overcome latency and have a smooth, well functioning multiplayer game where the players are oblivious to network problems.

Why not just incorporate the delay into the game itself? Give an animation showing your player's gun charging up before it fires or a unit responding to the command you just gave it (without actually moving yet). If you have your player driving an armored vehicle such as a tank, tell your player that in needs to shift into gear before it can move and play an audio clip of an engine sputtering while you wait for the server's go ahead signal.

Of course, you may want to standardize this delay somehow. If you relied on just latencies to create your delay, players with higher latencies would be hugely disadvantaged. Plus, the delay would be constantly changing and would throw the feel of it off completely.

Say we were to choose a delay of 500 ms to ensure that players will not experience latency higher then our delay (when players start to get pings higher then 500 ms you should really consider kicking them! It's good practice to try and allow everyone to play, but we must keep sane conditions! Often, a ping that high is also a sign we're exceeding their bandwidth as well)

This means that we want to delay sending this message back from the server a total of (500 - user's ping) ms in order for it to arrive 500 ms after it was sent. Of course, remember that we don't want to be sending individual messages due to overhead so this should be rounded to the nearest state update.

You may not want a delay on actions, however. Many gamers want "twitch" gaming where they can whip around and kill an enemy even before the other player has a chance to react. Unfortunately for us, it is actually the twitch factor the helps make these problems large. If someone is moving quickly, or things are happening quickly then network lag is that much more present and noticeable. If a player moves his entire body length in 300 ms and there is 300 ms lag on the network, he is ahead of himself by one body length.

With this amount of error, we can easily see that problems will begin to form. Noticeable contradictions will pop up and players will be annoyed. Fast moving entities cause problems for us. Remember that we are limited by the platform we chose. As much as you may want to make a twitch game, it is not very feasible for the casual market where you reach high pings on a regular basis.

If we were just to slow this guy down, what would happen? Our ping would stay the same but the amount of ground he covered in that time would be greatly reduced. Let us say the character moves his body length every second now, moving much more slowly than he was before. In the 300 ms it takes a message to reach the other end of our network, he has moved only 1/3 of his body length!

Even before our corrective measures, shooting at this guy or otherwise interacting with him would bring you decent success! Most of what we see on our screen overlaps with where he actually is on the server! Our problems due to latency are minimized in this scenario. Just by taking a certain amount of "twitch" out of our game and simply slowing everything down, we have seriously improved our game's resilience to latency.

Even when we have designed a game such that there are obvious and easily seen errors and inconsistencies, why should we make errors obvious and show all of our players what seemingly illogical contradictions are happening?

Earlier we looked at "enhancing the truth" now we will talk about smudging it. For example, if you have players shooting at one another in a heated battle, they'll barely be able to tell if they're missing or not unless you trace out the bullet lines for them.

Due to latency, shots that seemed to hit might not actually have hit or shots that seemed to miss might actually have hit, we don't actually want them to see if each shot hit or not, stopping them from working out these contradictions! By giving only a muzzle flash when they shoot or other similarly ambiguous visuals, we force the player to be unsure of what they see and they're more inclined to believe what the server tells them instead of what they might have seen. This is exactly what we're after!

Dealing with latency is more then just the programmer's responsibility. Talk with whoever is doing your art to ensure they can help in the facade.

Almost all of our problems that have to do with latencies have to do with players interacting with each other. In contrast, our surroundings are nice, easy stable and predictable! We don't really have any problem with it! The problems occur when we are interacting with another entity where we can't know it's exact state at that very moment.

Interactions between players are important, of course as they provide the foundations for a multiplayer game (if you didn't interact at all it would be single player!) but are ALL those interactions necessary? For example, do players really need to be able to bump into each other? Often these sorts of collisions are ugly and obviously laggy, annoying the player and making the game more clunky as they try to navigate around other players and bump into them even though they thought that they could get by (as the player is not shown at their correct location). Even worse would be a racing game where players are going fast! Collisions in this case can be simply disastrous and scare players away from your game. So, why make players collide at all? Few players will think twice about going through another and will more likely just be thankful that they can pass without hitting him.

There are multiple other examples of interactions that may or may not be necessary. Do you need knockback when explosions happen? If a player sees an explosion happen behind him but gets pushed as if it happened in front of him then they are going to be confused.

In general, you must think critically about any effects that one player has on another. Ask yourself if it is important to game play and if it is worth the possible error (or, if the errors will be significant).

Consider alternate solutions as well. For example, a developer might be reluctant to let players pass through each other because he wants them to be able to block doorways and/or become meat shields. This sort of scenario is easy enough to fix. Simply allow a player to entrench and block. Since they can no longer move, they become a static object just like the terrain. Collisions are made easy and can be done smoothly with no glitches.

Attack your problems with ingenuity and you may just become a master magician who is capable of making smooth and convincing real-time games!



Table of contents
1 - Introduction 8 - Synchronization
2 - Game Basics 9 - Interpolation
3 - Turn Based Games 10 - Latency
4 - Network Architectures 11 - Tips & Tricks
5 - Security 12 - Game: Turn Based
6 - Example Game 13 - Game: Realtime uninterpolated
7 - Real Time Games 14 - Game: Realtime interpolated


About the author

Ryan Brady is a Canadian developer who is currently going to the university of Waterloo. When he isn't fooling around with friends or dealing with an ungodly amount of course work, he likes to design and build games.

Two of the things Ryan likes most above all else are sarcasm and irony. Thus, he likes other people when they have a sense of humor and don't take offence at playful stabs and teasing. Otherwise, people tend to think Ryan hates them and/or the entire universe.

Subscribing to the "Work hard, Play hard" mindset, Ryan is always on the move. There are not enough hours in the day to do everything he wants to do (which is quite a bit). As a habit, Ryan designs more things then he has time to make. Alphas and proofs of concepts are his bread and butter though he always wishes he could make them into full games.

Every so often, you will see Ryan with a full beard on his chin. This commonly refereed to as Schrodinger's beard as you never know if Ryan will have it when you see him next. He re-grows it in under a week.

Every 4 months, Ryan has a co-op term so he moves around quite a bit. He might be living in Canada one month then be living in San Fran the next. You will never know when Ryan will be at large in your area next (until it is too late).