Skocz do zawartości

[GM:Studio] Networking - Czyli co i jak


Rekomendowane odpowiedzi

Witam ostatnio ogarnąłem Networking w GM:S i pomyślałem, że komuś może się przydać przykład jak zrobić coś takiego.

 

1.Co potrzebne?:

-Game Maker Studio Free,

-Cierpliwość.

 

2.Tworzymy serwer

Na samym początku tworzymy object oServer, dodajemy event Create i wklejamy kod:

GML
server = network_create_server( network_socket_tcp, 6510, 32 ); //Tworzymy serwer z naszym ip (localhost), portem 6510 i z maksymalną liczbą graczy 32

if( server<0 ) //Na wszelki wypadek upewniamy się czy serwer został stworzony.

{

show_message("Nie mozna sie polaczyc"); //Jeżeli nie to wyświetla komunikat.

game_end(); //I kończy gre

}

else // Jeżeli jednak udało się stworzyć serwer to

{

show_message("Pomyslnie utworzono serwer"); //Wyświetla komunikat, że udało się stworzyć serwer.

}

 

 

 

3.Tworzymy klienta

Teraz tworzymy obiekt oClient i w create wklejamy:

GML

client = network_create_socket( network_socket_tcp ); //Tworzymy socket

server = network_connect( client, "127.0.0.1", 6510 ); //Laczymy sie do serwera ip (localhost), i port (6510)

if server < 0 //Tak samo jak przy serwerze

{

show_message("Nie można się połączyc");

game_end();

}

else

{

show_message("Pomyslnie polaczono!");

}

 

4.Odbieranie danych od klienta

Aby serwer mógł odbierać dane od klienta należy utworzyć mape graczy oraz liste socketów

Więc w obiekt oServer w Create wklejamy kod:

GML
Clients = ds_map_create(); //Tworzmy mape klientów

socketlist = ds_list_create(); //Tworzmy liste socketów

idd = 0; //Przydatne do rozróżniania graczy</span></span></span></span>

 

Teraz w Event Networking:

416_NetworkEvent.png

Wklejamy:

GML
var eventid = ds_map_find_value(async_load, "id");

 

if( server == eventid )

{

var t = ds_map_find_value(async_load, "type"); //Typ polaczenia (połączył się/rozłączył się)

var sock = ds_map_find_value(async_load, "socket"); //Pobieramy jego sock

if( t==network_type_connect) //Jezeli ktos dolaczyl

{

ds_list_add( socketlist, sock ); //Dodajemy do listy

idd ++; //Dodajemy 1 do idd

ds_map_add( Clients, sock, idd ); //Dodajemy do mapy //idd - przypisujemy mu id

show_message("Nowy gracz dolaczyl!");

}

else //Jeżeli się rozłączył

{

var inst = ds_map_find_value(Clients, sock ); //Znajdujemy tego gracza

ds_map_delete(Clients, sock ); //Usuwamy go z mapy

var index = ds_list_find_index( socketlist, sock ); //Znajdujemy go w liscie

ds_list_delete(socketlist,index); //I usuwamy

}

}

else if( eventid!=0) //Jezeli nie rowna sie 0

{

var buff = ds_map_find_value(async_load, "buffer"); //Tworzymy buffer

var wiadomosc = buffer_read(buff, buffer_string ); //No i odbieramy dane

show_message(wiadomosc); //Wyświetlanie wiadomosc

//var sock = ds_map_find_value(async_load, "id"); //Przydatne do tego niżej

//var inst = ds_map_find_value(Clients, sock ); //Przydatne jeżeli chcemy określić od kogo to zostało wysłane

}

 

5.Odbieranie danych od serwera

Aby odbierać dane od serwera należy zrobić tak samo jak powyżej, ale nie trzeba dodawać mapy i listy do create.

Wystarczy

GML
var eventid = ds_map_find_value(async_load, "id");

 

 

if( client == eventid )

{

var buff = ds_map_find_value(async_load, "buffer");

cmd = buffer_read(buff,buffer_string);

show_message(cmd);

 

}

Tutaj chyba nie musze tłumaczyć

 

5.Wysyłanie danych do serwera

Wysyłanie jest bardzo proste. Spójrzcie na kod:

GML
var buff = buffer_create(256, buffer_grow, 1); //Tworzymy buffer

buffer_seek(buff, buffer_seek_start, 0); //Czyścimy go

buffer_write(buff, buffer_string,get_string("Podaj wiadomosc: ","")); //Wpisujemy do buffera naszą wiadomość

network_send_packet( client, buff, buffer_tell(buff) ); //Wysyłamy</span></span></span></span>

 

 

5.Wysyłanie danych do clienta

Jeżeli chcemy wysłać jakąś wiadomość wszystkim graczą wystarczy:

GML
var t_buffer = buffer_create(256, buffer_grow, 1); //Tworzymy buffer

buffer_seek(t_buffer, buffer_seek_start, 0); //Czyścimy go

buffer_write(t_buffer , buffer_string,get_string("Podaj wiadomość:","")); //Wpisujemy do buffera naszą wiadomość

for (var i = 0; i < ds_list_size(socketlist); i++;) //I wysyłamy do wszystkich graczy

{

network_send_packet(ds_list_find_value(Clients, i), t_buffer, buffer_tell(t_buffer));

}

 

Jednak jeżeli chcemy wysłać do jednego gracza musimy znać jego id czyli można użyć teraz sock

Np.

GML
buffer_seek(t_buffer, buffer_seek_start, 0);

buffer_write(t_buffer, buffer_u8, 3 );

buffer_write(t_buffer , buffer_s8, global.idd);

network_send_packet(ds_list_find_value(Clients, global.idd-1), t_buffer, buffer_tell(t_buffer));

Nie wklejacie tego do swojego projektu.

 

 

 

 

 

Gotowe! Jeżeli wszystko zrobiliście dobrze to powinno działać.

 

Przykład: Download

 

Przykład v2.0 (bez wytłumaczenia i nie ogarnięty troche kod): Download

 

 

Jeżeli coś nie działa, jakiś bulwers czy po prostu jakaś propozycja pisać w komentarze.

 

#CA14 - Uzjel

Odnośnik do komentarza
Udostępnij na innych stronach

a co z androidem?

Ludziom to nie dogodzisz, nie dość że wszystko pod nos podstawione screena nawet z eventem zrobił, a ten tu wyjeżdża z androidem. Poza tym w pierwszym punkcie masz że jest wymagana wersja FREE na której nie możesz robić gier na andka, więc może po prostu autor nie ma tego eksportu. W takim razie nie napisze pod niego tutoriala bo nie jest cudotwórcą żeby wyobrażać sobie efektów swojej pracy. :P Jak masz taki eksport to nikt nie broni Ci przeczytać dokumentacji i na podstawie tego co zrobił tutaj kolega Piotrek1910 zrobić multika na Andku, podejrzewam że dużo się nie różni chyba że chce grać przez Bluetooth.

Odnośnik do komentarza
Udostępnij na innych stronach

nie uruchomisz tego na zwykłych vpsach czy dedykach, a takie z karta graficzną zaczynaja się gdzieś od minimum 200-300$/miesiąc

dlatego jak ktoś chce robić gierke online to lepiej od razu dllki uzyć.

 

Ale to troche taki strzał w stopę, bo np dla androida aż się prosi robic gierki online a potem nie ma jak połączenia obsłużyć.

Odnośnik do komentarza
Udostępnij na innych stronach

  • 2 miesiące temu...
przy okazji mozna dopowiedzieć że wbudowany networking nie nadaje się do gier online, a jedynie do trybów multiplayer.

 

Eee aha czyli nie nadaje sie do robienia "masła" ale nadaje sie do robienia "masła". Logic. Jedno i to samo.

 

dlatego jak ktoś chce robić gierke online to lepiej od razu dllki uzyć.

 

Znów bzdura. Dllki, wszystkie, które są dostępne aktualnie na sieci dla GM'a są pisane albo tylko dla windowsa albo tylko dla desktopów, czyli nie są cross-platform. Wbudowany NOWY networking jest cross-platformowy - będzie więc działać tak samo na desktopach, androidach itp. Jest to co najmniej imponujące.

Fakt, że GMowej appki nie opłaca się odpalać na serwerach dedykowanych nie zostanie rozwiązany przez DLL'e bo przecież to wciąż będzie GAME MAKER ODPALAJĄCY DLL'a ;>. Tryb graficzny nadal zostanie. Jedyne co należy napisać sobie POZA game makerem to tzw. serwer globalny, który będzie tylko zbierał informacje o istniejących grach/serwerach i podsyłał listę serwerów dla graczy szukających gier.

 

Właśnie piszę sobie prosty multiplayer z obsługą UDP. Nowy networking jest o niebo lepszy od starego dziadostwa, który oferował GM.

Odnośnik do komentarza
Udostępnij na innych stronach

Tworzysz jeden buffer a potem do nie upychasz. Tu masz linka do typów bufforów. link

 

 

np.

Strona Clienta:

GML
var buff = buffer_create(256, buffer_grow, 1);

buffer_seek(buff, buffer_seek_start, 0);

buffer_write(buff, buffer_u8, 1 );

buffer_write(buff, buffer_s16, x);

buffer_write(buff, buffer_s16, y);

buffer_write(buff, buffer_s16, direction);

network_send_packet( client, buff, buffer_tell(buff) );

buffer_delete(buff); //Dobrze by było usunąć ten buffer jak go już wyślemy.</span>

 

Strona serwera:

GML
//Odbiera dane od clienta.

var t_buffer = buffer_create(256, buffer_grow, 1);

xx = buffer_read(buff, buffer_s16);

yy = buffer_read(buff, buffer_s16);

ddirection = buffer_read(buff, buffer_s16);

buffer_delete(t_buffer);

 

Wiem może to troche dziwne wygląda. Troche się to różni od 39dll.dll.

Odnośnik do komentarza
Udostępnij na innych stronach

Jedna mała uwaga - ten kod który podałeś wyżej nie do końca działa, musiałem dać tak jak było w poprzednim przykładzie:

 

GML
var buff = ds_map_find_value(async_load, "buffer");

 

zamiast

 

GML
var t_buffer = buffer_create(256, buffer_grow, 1);
Odnośnik do komentarza
Udostępnij na innych stronach

Co do buffera to moim zdaniem nie ma sensu robić nowego za każdym razem jak wysyłasz wiadomość. Ja sobie zrobiłem 1 buffer w CREATE mojego obiektu odpowiedzialnego za synchronizację i tym bufferem sie posługuje przez cały okres wymiany danych, niszczę go wraz ze zniszczeniem obiektu.

Dla jasności, to nie jest tak, że wysyłasz buffer po sieci. Buffery to jedynie sposób trzymania danych binarnych w GM:Studio, dlatego przy wysyłaniu piszesz buffer_tell(buff) - co oznacza miejsce, do którego są zapisane dane w bufferze. Funkcja wysyłająca zczytuje dane do tego miejsca w bufferze i wysyła już tylko informacje tam zapisane, a nie zaś sam buffer.

Odnośnik do komentarza
Udostępnij na innych stronach

  • 2 tygodnie później...
nie uruchomisz tego na zwykłych vpsach czy dedykach, a takie z karta graficzną zaczynaja się gdzieś od minimum 200-300$/miesiąc

dlatego jak ktoś chce robić gierke online to lepiej od razu dllki uzyć.

 

Ale to troche taki strzał w stopę, bo np dla androida aż się prosi robic gierki online a potem nie ma jak połączenia obsłużyć.

bullshit, wystarczy napisać serwer w C++ choćby i nawet...

Odnośnik do komentarza
Udostępnij na innych stronach

  • 2 tygodnie później...

Pieter, sądzę, że troche trudno by było. Trzeba wiedzieć jakie dane gms oczekuje od serwera.

Ja np. napisałem sobie prosty serwer winsock i połączyłem się pod niego w gms. No i niestety mój program gms się zawiesił.

A jak próbowałem odwrotnie stworzyłem serwer w gms i połączyłem się dzięki winsocku to serwer nie miał żadnej reakcji, że coś się stało. A jak zakończyłem prace klienta to nagle serwer się obudził mówiąc, że ktoś wyszedł z serwa.

Tyle.

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...