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

in #polish6 years ago

Poradnik: Jak napisać grę multiplayer RPG

szybko i przyjemnie

rpg-468920_1920.jpg

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

Coin Marketplace

STEEM 0.30
TRX 0.12
JST 0.034
BTC 64136.70
ETH 3128.20
USDT 1.00
SBD 3.94