Poradnik: Jak napisać grę multiplayer RPG szybko i przyjemnie

Poradnik: Jak napisać grę multiplayer RPG

szybko i przyjemnie

Zasady

Pierwsza: nie zrobisz w ten sposób super hiper mega MMO

Druga: jest masa lepszych sposobów aby to zrobić, ten jest prosty i mój

Trzecia: możesz to traktować jako wstęp, ogólną ideę

Czwarta: używam C++ i SFML

Piąta: najpierw przeczytaj potem patrz kod na githubie 🙂

Pierwsze kroki

Zaczynamy od stworzenia klienta i serwera. Tutaj klient służy do komunikacji z serwerem i do wyświetlania świata gry. Serwer otrzymuje komendy od klienta i na ich podstawie aktualizuje świat gry i wysyła kopię do klienta. Świat składa się z graczy, przedmiotów, obiektów itd.

Na początek przygotowujemy połączenie. Skoro doszedłeś do etapu, gdzie chcesz programować swoją grę multiplayer to zakładam, że sobie poradzisz z tą prostą czynnością. Tutaj masz link: https://www.sfml-dev.org/tutorials/2.4/network-socket.php

Dodanie gracza do serwera

Zadania:

  • gracz potrzebuje unikalnego ID po stronie serwera
  • musimy dodać gracza do Świata
  • trzeba wysłać informacje o nowym graczu do klientów

Tak więc, kiedy klient łączy się z serwerem to on musi zrobić jakieś unikalne ID. Ja to zrobiłem w ten sposób:

std::string player_id = „player_id__” + std::to_string(reinterpret_cast<uint32_t>(client)); 

W ten sposób mamy ID dla gracza. Po prostu pobiera z pamięci adres clienta i robi z tego string. Wystarczająco dobre dla prostej, lokalnej gry.

world->addPlayer(Player(player_id, sf::Vector2f(100, 100), sf::Vector2f(66, 92), 100));

Tak dodajemy gracza do świata z wcześniej utworzonym id, pozycją, rozmiarem i życiem.

Następnie wysyłamy informację o graczu do klienta.

sf::Packet start_packet;
start_packet << "connect" << *world->getPlayer(player_id); 
client->send(start_packet);

Strona klienta:

– wydobywamy ID gracza z otrzymanego pakietu i przechowujemy go w kliencie (pozwoli nam to informować serwer kim jesteśmy)

Więc kiedy otrzymamy pakiet sprawdzamy czy to jest ‚connect’ i wydobywamy ID gracza i przypisujemy do client_player_id = received_id;

Logika

Reszta logiki jest podobna. Na przykład:

Klient wysyła komendę ‚update world’ – serwer po otrzymaniu tego wysyła cały świat do gracza

Kiedy klient otrzyma ‚update world’ podmienia świat na ten, który dostał z serwera

Klient wysyła ‚move player up’ i swój id do serwera, który przesuwa gracza o danym id w górę

Sprawa jest ogólnie prosta. Zobacz na mój przykładowy kod do komunikacji pomiędzy klientem i serwerem.

Klient:

void Client::runCommand(const std::string& command, const std::string& id)
{
  if(command == "player move")
    {
      sf::Packet packet;
      packet << "player move" << id << player_id;
      socket.send(packet);
    }
  if(command == "destroy item")
    {
      sf::Packet packet;
      packet << "destroy item" << id;
      socket.send(packet);
    }
} 

To jest część kodu z klasy Client. Używam tutaj prostej funkcji, która wysyła polecenia do serwera.

Serwer:

sf::Packet packet;
if(client.receive(packet) == sf::Socket::Done)
{
    std::string event;

    if(packet >> event)
    {
        if(event == "player move")
        {
            std::string player_id;
            std::string direction;
            if(packet >> direction >> player_id)
            {
                if(direction == "up")
                    world->getPlayer(player_id)->position.y -= 5;
                if(direction == "down")
                    world->getPlayer(player_id)->position.y += 5;
                if(direction == "left")
                    world->getPlayer(player_id)->position.x -= 5;
                if(direction == "right")
                    world->getPlayer(player_id)->position.x += 5;
            }
        }
        if(event == "update world")
        {
            sf::Packet send_packet;
            send_packet << "update world" << *world;
            client.send(send_packet);
        }
        if(event == "destroy item")
        {
            std::string item_id;

            if(packet >> item_id)
            {
                world->removeItem(item_id);
            }
        }
    }
}

Podsumowanie

Może nie jest to idealne  rozwiązanie. Może nie robi się tak gier. Nie takie jest zadanie tego postu. Ma on pokazać ogólną ideę stojącą za komunikacją w grach pomiędzy serwerem i graczem. Nawet jeśli nie jest to zrobione idealnie to dla mnie jest to kod z którego jestem dumny. Nie ma dobrych poradników, które za rękę poprowadzą kogoś jak się robi gry multiplayer. Przynajmniej nie było kiedy to programowałem (rok 2015). Jestem na tyle dumny z tego kodu, że często się nim posługuję pokazując, że jestem w stanie samemu wymyślić sposób aby rozwiązać jakiś problem.

Obiecany kod

Github: PMR – Patys MMO RPG

 

4
Dodaj komentarz

avatar
3 Comment threads
1 Thread replies
1 Followers
 
Most reacted comment
Hottest comment thread
4 Comment authors
the art of public speaking connect access cardMichałPatyskordian Recent comment authors
  Subscribe  
najnowszy najstarszy oceniany
Powiadom o
kordian
Gość
kordian

Jest to już coś grywalnego? Masz jakieś screeny?

Michał
Gość
Michał

Wielkie dzięki, że wrzuciłeś kod, bardzo mi pomogłeś.

the art of public speaking connect access card
Gość

Hi just wanted to give you a quick heads up and let you know a few of the pictures aren’t loading properly. I’m not sure why but I think its a linking issue. I’ve tried it in two different internet browsers and both show the same outcome.| а