Coop Modus - Multiplayer Indie Game - Gether

A cooperative game

The Project Gether is a thoroughly cooperative video game without a single player mode.

How do you do that?

Who has ever developed a game from scratch knows how complex the entire development process can be. In a multiplayer game, the effort increases by one difficulty level. To develop a multiplayer game you have to think from the beginning about which things can be manipulated (visuals like skins, tiles, etc.) and which can't (character position, etc.).

Trivial principle for data exchange.

If you develop a game like we do, in which there should be a maximum of two players, you can, of course, do without many things. So it is not important that the server validates every new character position and prevents teleportation hacks, because usually the players only spoil the fun for themselves.

Other it would be in a MMORPG with thousands of strange players, who probably wouldn't find it so exhilarating, if someone teleports through the whole map to dust the best items, for example.

SFML - Send & receive packets (TCP)

Since we work with SFML, we also use the network capabilities that SFML offers us. To send a packet over TCP we need a valid existing connection.

This connection is established by calling the connect method.

int port = 7777;
sf::TcpSocket socket;
socket.connect("127.0.0.1", port);

Here we assume that a server is running on our home computer under the port 7777. To create such a server, we use the listen.

Vielleicht auch interessant
Die Idee - Multiplayer Indie Game - Gether
Die Idee - Multiplayer Indie Game - Gether

Erste Anreize und die Idee hinter meinem Multiplayer Game Projekt.

method.
sf::TcpListener listener;
listener.listen(port);

sf::Socket client;
if(listener.accept(client) == sf::Socket::Done)
{
// connected
}

SFML blocks the application by default until someone connects, sends and receives packets. This causes our game to freeze quite often when we work in mainthread. To prevent this, we disable blocking with setBlocking.

socket.setBlocking(false);
client.setBlocking(false);

To send packets to the server, we use send.

sf::Packet packet;
packet << 1.0f << 2.0f;

if(socket.send(packet) != sf::Socket::Done)
{
// Error!
}

Very important is here that it cannot be guaranteed that packets will always be sent successfully. This means that a mechanism must be implemented which resends the failed packets in the correct order.

That could look like this:

processFailedPackets();

if(socket.send(packet) != sf::Socket::Done)
{
// std::vector<sf::Packet>
failedPackets.push_back(packet);
}

To receive packets on the server side, we have to call the method receive, here we have to consider that the method is only called at one point in the source code (per socket).

sf::Packet packet;
if(client.receive(packet) == sf::Socket::Done)
{
float a, b;
packet >> a >> b;
}

More...

Of course that was just the basic logic. For an entire game project it becomes slightly more complex. Usually you package the whole thing in classes and strictly separate server logic from client logic. How I realized this for Gether can be seen in the finished project. The whole source code will be available at the end.

Next article
Gether - Final (Full Code)
Leave a like or comment (~‾▿‾)~
Name Text