Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
SFML Game Development.pdf
Скачиваний:
194
Добавлен:
28.03.2016
Размер:
4.19 Mб
Скачать

Company Atop the Clouds – Co-op Multiplayer

The new Player class

The Player class needed to be reworked quite a bit in order to support a multiplayer mode. Players are not hardcoded anymore in a state context scope, but rather, there is one player for each human-controlled aircraft in the world.

Every player is now identified by the same identifier that classifies one aircraft, so they can be paired up fast. Also, the constructor of Player now looks like the following:

Player(sf::TcpSocket* socket, sf::Int32 identifier, const KeyBinding* binding);

We pass on a socket instance or a nullptr, defining whether the Player class is being used in a networked or a single-player game. This socket, if passed, is valid for sending data to the server, which we will do next!

The identifier is exactly what you'd expect, the same that maps to an aircraft too.

Finally, we also have KeyBinding being passed here. We will be passing it three different things: The defined keys for the player 1, player 2, and nullptr in case this Player instance does not receive local input, but rather is controlled by the server!

As for event and input handling by the Player class, it now works a little differently too.

Now, the real-time input is only delivered to the local player aircraft—the ones with actual human players controlling them. In consequence, each client has total control over its planes along with immediate responsiveness and smoothness. At the same time, that input is sent to the server, so every client is aware of that movement.

Latency

Programming and maintaining efficient server software is already a very hard task; however, to add even more complexity to this duty, we must deal with latency too. This topic is very broad but we will still try to give you some starting tips on how to deal with these issues.

Roughly, latency is the delay a network packet takes to reach its destination. The bigger the latency, the more we get behind in the networked simulation, and in consequence, the gameplay gets worse.

[ 264 ]

www.it-ebooks.info

Chapter 10

This little nightmare is one of the hardest troubles to deal with in network programming. It will make players have a different experience based on their connection and other network conditions, that is, it will make the game very smooth for some players while completely unplayable for others; it will be a mess. Unfortunately, it is not in the hands of the programmer to deal with the network's latency at all. A programmer can at best prepare the software to behave a little better in the worst case scenarios, where the latency is high. This is usually a very hard task to get right and is one of the main reasons game development companies need specialized and experienced network programmers to achieve a good simulation for all players, independently of how bad their connection is, within reasonable limits. Latency becomes a more and more determining factor as the geographical distance between peers increases. Already the speed-of-light delay between different continents of the Earth amounts to a fraction of a second, router logic on the way through the Internet may add even more. Until a peer receives an answer, data must be sent to the other peers and back; thus, we have the delay of both ways (also called round-trip time). Therefore, physics significantly limits the way how multiplayer games can be played across large distances.

Latency versus bandwidth

Do not confuse latency with bandwidth: The former denotes the time delay, while the latter denotes the capacity of the link. If you imagine a link as a pipe, the latency is related to its length, and thus to the time the water requires to flow through it. Bandwidth however is determined by the cross-section of the pipe; it specifies how much water can flow through it in a certain amount of time.

You cannot make a single bit arrive faster by increasing the bandwidth. What you can do however is to send many bits in parallel, so that a bigger chunk of data still needs less time to be transmitted. The bandwidth determines how much data you can send in a certain amount of time.

View scrolling compensation

The view is now simulated both in the client and the server and updated at the same speed in both of them. However, since the updates are happening in different threads or even different machines, some discrepancies may occur occasionally. Also, when a new player joins the game, he has to be informed of how far the view currently is, so it can keep up with it. In order to keep the view synchronized between all clients and the server, the server will send the view's position in every tick and the clients will employ a little trick to smoothly resynchronize the view.

[ 265 ]

www.it-ebooks.info

Company Atop the Clouds – Co-op Multiplayer

The trick is simple. When the view is scrolled, we multiply the scroll offset with a compensation factor:

mWorldView.move(0.f, mScrollSpeed * dt.asSeconds() * mScrollSpeedCompensation);

Now we just need to ensure that the factor is 1 when the views are in sync, and vary it, so the view scrolls faster or slower depending on how distanced it is from the server's view position. We do this by dividing both positions whenever we get the update:

mWorld.setWorldScrollCompensation(currentViewPosition / currentWorldPosition);

This will keep the view synchronized while never losing smoothness, unless something is very wrong and is too far behind, which should never happen in normal circumstances.

Aircraft interpolation

After the compensation technique, we decided to implement another little trick for the aircraft synchronization. Again, this is a simple way to achieve synchronization and it doesn't give the smoothest results most often. We still wrote it so you could face different algorithms and techniques and hopefully learn from them.

Remember, that each client commands its own planes and just informs the server of what is happening locally. With this information, the server keeps track of where every aircraft that is located. In every tick, it sends that information to its peers so they can synchronize with the true simulation data.

The planes would move quite accurately anyway with the real-time input information that comes from the server, but still some desynchronization could happen eventually. Because of this, when we get the real position of the aircraft in every tick, we move our aircraft slowly into that position, so, at best, after some ticks the aircraft are completely synchronized:

if (aircraft && !isLocalPlane)

{

sf::Vector2f interpolatedPosition = aircraft->getPosition() + (aircraftPosition - aircraft->getPosition()) * 0.1f; aircraft->setPosition(interpolatedPosition);

}

[ 266 ]

www.it-ebooks.info

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]