Skocz do zawartości

Mplay nie przesyła danych.


Jemkam

Rekomendowane odpowiedzi

Witam wszystkich użytkowników tego forum. Niestety sprowadza mnie tu dość kłopotliwy problem. Od paru dni męczę się z tworzeniem jakiejś małej gierki multiplayer, takiego bardziej przykładu by zapoznać się z tego typu rozwiązaniami. Zacząłem od napisania programu własnoręcznie za pomocą mplay, jednak nie funkcjonował on tak jak należy. Postanowiłem więc podpatrzeć jak to jest zrobione na różnych przykładach i tu mnie wmurowało! One także nie działały!. Mowa tu o przykładach, które dotyczą gry wieloosobowej dla większej liczby graczy niż 2. Cały ich system opiera się na wysyłaniu danych od gracza (Player) do kontrolera (Controller), który przetwarza je i rozsyła do innych. W ten sposób widza oni przemieszczenie się innych graczy (OtherPlayer). Za cel obrałem więc sobie próbę naprawienia tych przykładów. Sprawdzając poszczególne linijki kodu doszedłem do wniosku, że nie działa komunikacja Gracz-Kontroler. Więc spróbowałem to zrobić na swój sposób za pomocą funkcji "mplay_data_write" oraz "mplay_data_read", resztę schematu pozostawiłem jak było w przykładach. Po sprawdzeniu wiedziałem już, że udaje się wysłać wysłać informacje do kontrolera, który odpowiednio tworzy "otherplayery" jednak... No właśnie tutaj jest ten problem. Kiedy uruchamia się parę klientów gry (np.2) to w każdym z nich kontroler nie steruje otherplayer tak jak robi to ten drugi gracz, tylko tak jak ten aktualnie grający. Poruszając się naszym bohaterem w jednej grze widzimy tylko własne ruchy, gdyż kontroler przesuwa "otherplayer" zależnie od wytycznych naszego ludzika, a nie tak jak powinno być tego drugiego. Nie mam już pomysłów co może być tego przyczyną, chciałbym by cały program działał prawidłowo, czyli gracz1 wysyła o sobie informacje do kontrolera, który z kolei je przetwarza i wysyła do innych graczy u których pojawia się jak by "duch" tego gracza a konkretniej otherplayer. Obecnie natomiast w tej ścieżce na poziomie kontrolera informacja zawraca do gracza który ją wysyła. Tak mi się przynajmniej wydaje.

PS. Bardzo liczę na pomoc, jeżeli to co napisałem jest niejasne mogę postarać się opisać to w inny sposób. Dodam jeszcze, że używam gamemaker w wersji 8.1.141.

Odnośnik do komentarza
Udostępnij na innych stronach

Już wklejam. Jest to kod z eventu step obiektu "Controller". Jest to w dużej mierze przykład, ja tylko podmieniłem "mplay_data_write/read" bo stosowany tam sposób kompletnie nie działał:

GML
//if mplay_message_receive(0) //je�eli otrzymuje wiadomo�� to wybierz :

wiadomosc=mplay_data_read(10);

switch mplay_data_read(11){

case 0 :

o=instance_create(50,50,OtherPlayer); //gracz do��czy� do gry

Value=mplay_data_read(10);

o.Number=real(string_copy(Value,0,string_pos("|",Value)-1)); //inicjuje numer gracza, funkcja real zmienia z tekstu na liczb�

Value=string_copy(Value,string_pos("|",Value)+1,string_length(Value)); //skraca tekst o liczb� i znak "|"

o.x=real(string_copy(Value,0,string_pos("|",Value)-1)); //pobiera pozycje gracza, funkcja real zmienia z tekstu na liczb�

Value=string_copy(Value,string_pos("|",Value)+1,string_length(Value)); //skraca tekst o liczb� i znak "|"

o.y=real(string_copy(Value,0,string_pos("|",Value)-1)); //pobiera pozycje, funkcja real zmienia z tekstu na liczb�

Value=string_copy(Value,string_pos("|",Value)+1,string_length(Value)); //skraca tekst o liczb� i znak "|"

o.name=string(string_copy(Value,0,string_pos("|",Value)-1)); //pobiera pozycje, funkcja real zmienia z tekstu na liczb�

//mplay_message_send(0,1,string(global.player_number)+"|"+string(x)+"|"+string(y)+"|"+string(Player.imie_gracza)); //odpowiedz, �e tak�e istniejesz

paczka=string(global.player_number)+"|"+string(x)+"|"+string(y)+"|"+string(Player.imie_gracza);

mplay_data_write(11,1);

mplay_data_write(10,paczka);

break;

case 1 :

o=instance_create(50,50,OtherPlayer); //gracz do��czy� do gry

Value=mplay_data_read(10);

o.Number=real(string_copy(Value,0,string_pos("|",Value)-1)); //inicjuje numer gracza, funkcja real zmienia z tekstu na liczb�

Value=string_copy(Value,string_pos("|",Value)+1,string_length(Value)); //skraca tekst o liczb� i znak "|"

o.x=real(string_copy(Value,0,string_pos("|",Value)-1)); //pobiera pozycje gracza, funkcja real zmienia z tekstu na liczb�

Value=string_copy(Value,string_pos("|",Value)+1,string_length(Value)); //skraca tekst o liczb� i znak "|"

o.y=real(string_copy(Value,0,string_pos("|",Value)-1)); //pobiera pozycje, funkcja real zmienia z tekstu na liczb�

Value=string_copy(Value,string_pos("|",Value)+1,string_length(Value)); //skraca tekst o liczb� i znak "|"

o.name=string(string_copy(Value,0,string_pos("|",Value)-1)); //pobiera pozycje, funkcja real zmienia z tekstu na liczb�

break;

case 2:

with(OtherPlayer){

Value=mplay_data_read(10);

Controller.wiadomosc1=Value;

NNumber=real(string_copy(Value,0,string_pos("|",Value)-1)); //inicjuje numer gracza, funkcja real zmienia z tekstu na liczb�

Value=string_copy(Value,string_pos("|",Value)+1,string_length(Value)); //skraca tekst o liczb� i znak "|"

xx=real(string_copy(Value,0,string_pos("|",Value)-1)); //pobiera pozycje gracza, funkcja real zmienia z tekstu na liczb�

Value=string_copy(Value,string_pos("|",Value)+1,string_length(Value)); //skraca tekst o liczb� i znak "|"

yy=real(string_copy(Value,0,string_pos("|",Value)-1)); //pobiera pozycje, funkcja real zmienia z tekstu na liczb�

Value=string_copy(Value,string_pos("|",Value)+1,string_length(Value)); //skraca tekst o liczb� i znak "|"

img=real(string_copy(Value,0,string_pos("|",Value)-1)); //zmienia obrazek gracza, funkcja real zmienia z tekstu na liczb�

Value=string_copy(Value,string_pos("|",Value)+1,string_length(Value)); //skraca tekst o liczb� i znak "|"

nam=string(string_copy(Value,0,string_pos("|",Value)-1)); //pobiera pozycje, funkcja real zmienia z tekstu na liczb�

Controller.wiadomosc2=string(xx)+"|"+string(yy);

if (Number=NNumber){ //je�eli numer gracza pasuje numerowi przys�anemu przez drugiego gracza

x=xx;//to zmie� jego pozycje i obraz

y=yy;

image_single=img;

name=nam;}}

wiadomosc3=string(OtherPlayer.x)+"|"+string(OtherPlayer.y);

break;

case 3:

with(OtherPlayer){

if (Number=real(mplay_message_value()))

instance_destroy();} //gracz od��cza si�}

break;}

 

PS. Zmienne z nazwą "wiadomosc" służył tylko temu bym mógł wyświetlić konkretne parametry na ekranie by sprawdzić czy są odpowiednio przetwarzane.

Odnośnik do komentarza
Udostępnij na innych stronach

  • Administratorzy

No dobrze, z tego co rozumiem z dokumentacji, to mplay_data_write() wysyła dane do wszystkich pozostałych graczy. Zatem kazdy gracz musi dostac swoje inne identyfikatory, np. pozycje X i Y gracza 1 to ind =1,2, gracza 2 to ind = 3,4 itd. Wtedy nie będą się nakładać.

Odnośnik do komentarza
Udostępnij na innych stronach

No tak, jednak wtedy gra byłaby przeznaczona dla określonej liczby graczy, ponieważ musiałbym już na początku utworzyć odpowiednią liczbę zmiennych.

W tym przykładzie pozycje każdego gracza są wysyłane jednakowymi identyfikatorami, jednak razem z nimi wysyłane są inne informacje. Między innymi jest to numer gracza, który zostaje sprawdzony w linijce "if (Number=NNumber)". Jeżeli numer gracza przysłany z konkretną wiadomością zgadza się z numerem gracza nadanym Otherplayer to znak, że te dane dotyczą jego.

Odnośnik do komentarza
Udostępnij na innych stronach

Zauważyłem, że numery dla otherplayer controller dodaje także wyłącznie na aktualnym kliencie. Gracz, który hostuje serwer ma na ekranie otherplayer z numerem 0, natomiast kolejni gracze, którzy dołączają do gry mają kolejne numery. Czyli jest tak samo jak z np. współrzędnymi czy innymi danymi, które controller powinien rozsyłać do innych graczy.

Odnośnik do komentarza
Udostępnij na innych stronach

  • 2 tygodnie później...

Witam ponownie. Już chyba wiem gdzie jest błąd, jednak mam z tym związane pytanie. Jak za pomocą kodu step w jednym obiekcie stworzyć inny z konkretnymi parametrami i zmiennymi. Tak aby stworzyć w zasadzie nieograniczoną ilość tego samego obiektu, tylko każdy miałby inną zmienną "numer". Według przykładu, o którym wcześniej wspominałem powinno to być rozwiązane w taki sposób:

GML
o=instance_create();

o.numer=(*);

Czyli zostaje stworzony obiekt wymieniony w instance_create i dostaje wszystkie zmienne, które mają o. przed nazwą. Jednak mam wrażenie, że nie funkcjonuje to prawidłowo ponieważ program tworzy tylko jeden taki obiekt o wówczas wymienionych parametrach i później go ani nie powiela, ani nie tworzy nowych, a także nie zastępuje starych.

Odnośnik do komentarza
Udostępnij na innych stronach

Dobrze, dzięki. Jednak okazał się, że wcześniejszy przykład prezentowany prze zemnie też jest prawidłowy tylko było trzeba to trochę inaczej zorganizować. Teraz od paru dni męczę się z przesyłaniem nicku gracza. Cały program napisałem od nowa i wszystko działa, jednak źle przesyła nazwę użytkownika. U pierwszego gracza, który zakłada grę, jego nick jest wyświetlany prawidłowo, natomiast innych jako np. literka "z". U innych graczy, którzy dołączają do gry wszystkie wyświetlane nicki to "0".

Oto fragment kodo programu odpowiedzialny za przesyłanie nicku.

Obiekt "Player", event "Create":

GML
player_number=real(mplay_player_find()-1)

imie_gracza=get_string("Imie gracza : ","");

mplay_data_write(5,player_number);

mplay_data_write(6,string(imie_gracza));

mplay_data_write(1,1);

Obiekt "Controller", event "Step":

GML
switch (mplay_data_read(1))

{

case 1:

o=instance_create(100,100,OtherPlayer);

o.Name=mplay_data_read(6);

o.Numer=mplay_data_read(5);

mplay_data_write(1,0);

break;

}

Odnośnik do komentarza
Udostępnij na innych stronach

  • Administratorzy

Wydaje mi się, że z tym switchem to źle podchodzisz. W mplay kazdy z tych buforów to rodzaj zmiennej synchronizowanej/flagi, tzn. mplay_data_write przesyła aktualną wartość danej zmiennej, żeby u reszty graczy zaktualizowało. Ja bym to porównał do zmiennej x i y w obiekcie - nawet jak jej nie modyfikujesz masz wartość. To nie są stosy ani bufory. To jest tylko polecenie na zasadzie "zaktualizuj zmienną numer XX". Zatem równie prawidłowe jest draw_text(x,y,mplay_data_read(6)); bo to polecenie tylko sprawdza w pamięci na jaką wartośc ostatnio ustawiono tę zmienną.

 

Zatem nie potrzebujesz switcha, zeby wiedziec co aktualnie ustawiłes - bo po prostu kazda zmienna powinna oznaczac w grze co innego i tyle.

 

 

Edit: jeszcze inaczej. Załóż, że jak inicjujesz mplay to masz tablicę 10000 elementów i mplay_data_write po prostu nadaje nową wartość tej tablicy dla wszystkich graczy. Wiem, że tak nie można pisac, ale umówmy się, że jest taki pseudokod:

mplay_data_write(ind, val) <==> with (all players) global._mplay[ind] = val;

Odnośnik do komentarza
Udostępnij na innych stronach

Switch było tam ponieważ wcześniej obiekt Controller obsługiwał o wiele więcej operacji. Jednak przerzuciłem większość z nich (np. poruszanie się) do poszczególnych obiektów w tym OtherPlayer. Faktycznie już switch zmieniłem na if. Co natomiast tyczy się choćby mplay_data_write(1,.) oraz read(1)... Mam parę takich zmiennych mplay ponieważ w ten sposób poszczególne obiekty wysyłają zapytania o konkretne dane i wówczas je otrzymują. Jest to potrzebne ponieważ tą samą drogą wysyłam np. zmienne wszystkich obiektów, tylko, że odbiera je jedynie ten obiekt który wysłał po nie zapytanie. Jednak nadal to nie rozwiązuje mojego problemu w nickami. Zauważyłem, że problem leży właśnie w przesyłaniu tej informacji między Player a Controller. Kiedy gracz pierwszy, ten który zakłada serwer dołączy do gry i nazwie się np. "ja", zmienna mplay (6) przybiera wartość "ja". W ten sposób nick pierwszego gracza wyświetlany jest prawidłowo. Następnie do gry dołącza gracz drugi i nazywa się np. "ty". Zmienna mplay (6) u gracza 1 przybiera wartość "z" i tak także wyświetla tego gracza. Natomiast u gracza drugiego zmienna (6) przybiera wartość "ty" i obu graczy w ten sposób podpisuje.

Odnośnik do komentarza
Udostępnij na innych stronach

  • Administratorzy

Jak napisałem, zmienna 6 zostanie ustalona dla wszystkich graczy. To nie jest tak, ze coś wysyłasz i odbierasz, to jest tak, że wysyłasz aby się zmienna 6 ustawiła na jakąś wartość wszystkim. Zatem nadpisze poprzednią wartość. Żeby wiedzieć, że nadszedł nowy pakiet, trzeba by zrobić zmienną która trzyma poprzednią wartość, bo mplay nie ma funkcji do odbierania wysyłania/pakietów, jedynie do synchronizacji zmiennych. Zatem wszelkie switche itp. mogą działać całą grę, podczas gdy w normalnej sieciówce powinny tylko gdy nadejdzie pakiet.

Odnośnik do komentarza
Udostępnij na innych stronach

No tak, ja to rozumiem, ale zauważ, że oprócz wysłania przez mplay nazwy gracza wysyła jego numer. A imię jego zostaje nadane tylko jeśli numer Otherplayer zgadza się z numerem gracza, którego imię wysłano. Oprócz tego przykładu kodu co tu umieściłem, próbowałem też zrobić, by obiekt Otherplayer sam pobierał swoje imię zależnie od numeru gracza, ale też to nie działało. Co do switcha, który może działać całą grę, to zawsze robię tak, że jeżeli pewien warunek zostaje spełniony to wykonuje wszystko co do niego podpisałem, a jak to zakończy przestawia ten warunek na fałsz i ponownie wykonuje te funkcję kiedy dostaje polecenie z innego źródła.

if (warunek=1)

{

(czynności)

warunek=0;

}

PS. Ten kod co go umieszczałem parę postów wcześniej prawidłowo nadaje numer gracza, zawsze nadaje go prawidłowo. Natomiast z nickiem już dzieją się różne dziwne rzeczy.

Odnośnik do komentarza
Udostępnij na innych stronach

Nie, nie używam. Błąd jest właściwie w samym momencie wysłania tej zmiennej mplay(6). Bo jak ją pobiera u gracza jako imie_gracza to zapisuje ją prawidłowo, a gdy ją wysyła to cuda się dzieją.

Proponujesz 39dll. Jest to więc bardziej rozwinięta biblioteka? Jest trudniejsza od mplay?

 

edit:

Zabrałem się jeszcze raz za napisanie tego programu, w inny sposób. Jednak błąd nadal jest ten sam. W pierwszym kliencie wszystkie OtherPlayer mają nick właściciela, w kolejnych nie mają.

Oto cały kod programu, w zasadzie to dopiero jego początek, ale już na tym stopniu nie działa:

 

Obiekt Player, event Create:

GML
numer_gracza=real(mplay_player_find()-1)

imie_gracza=get_string("Imie gracza : ","");

pz_mplay=(numer_gracza*10)+100;

mplay_data_write(5,numer_gracza);

mplay_data_write(pz_mplay+1,imie_gracza);

mplay_data_write(1,1);

 

Również obiekt Player, event Step:

GML
if keyboard_check(vk_up){

y-=5;

mplay_data_write(pz_mplay+3,y);

}

if keyboard_check(vk_down){

y+=5;

mplay_data_write(pz_mplay+3,y);

}

if keyboard_check(vk_left){

x-=5;

mplay_data_write(pz_mplay+2,x);

}

if keyboard_check(vk_right){

x+=5;

mplay_data_write(pz_mplay+2,x);

}

 

Obiekt Controller, event step:

GML
if (mplay_data_read(1)=1)

{

o=instance_create(100,100,OtherPlayer);

o.numer=mplay_data_read(5);

mplay_data_write(1,0);

}

 

Obiekt OtherPlayer, event step:

GML
pz_mplay=(numer*10)+100;

name=mplay_data_read(pz_mplay+1);

x=mplay_data_read(pz_mplay+2);

y=mplay_data_read(pz_mplay+3);

 

oraz ten sam obiekt, event draw:

GML
draw_text(x,y-16,mplay_data_read(pz_mplay+1));

draw_sprite(sprite1,1,x,y);

 

Oraz (to chyba nieistotne) kody eventu Left mouse button, obiektów odpowiedzialnych za zakładanie gry i dołączanie:

GML
mplay_init_tcpip(get_string("Adres IP : ","127.0.0.1"));

 

mplay_session_create("GMClanServer",200+1,"Gracz");

room_goto_next()

 

GML
mplay_init_tcpip(get_string("Adres IP : ","127.0.0.1"));

 

if mplay_session_find()!=0

{

mplay_session_join(0,"Gracz2");

room_goto_next()

}

else

{

show_message("Nie udalo sie dolaczyc do gry!")

}

Odnośnik do komentarza
Udostępnij na innych stronach

No to wtedy działa prawidłowo, gracze nazywają się zależnie od swojego numery (Gracz 1, Gracz 2....). Mi jednak chodzi by każdy z graczy mógł podać swoje imię, pod którym byłby wyświetlany. Na moje właśnie dowodzi to tego, że coś z get_string jest źle.

 

Edit:

Jednak spróbowałem jeszcze raz. Wstawiłem "imie_gracza = "Gracz " + string(numer_gracza);" tuż przed "mplay_data_write(pz_mplay+1,imie_gracza);" w obiekcie Player, event Create. Pierwszy gracz (założyciel serwera) został wyświetlony jako Gracz 0, natomiast kolejny już jako samo "0".

Odnośnik do komentarza
Udostępnij na innych stronach

  • 2 tygodnie później...

Już trochę czasu minęło a ja nadal nie umiem rozwiązać tego problemu. Wszystko wskazuje na to, że jest jakiś problem z przesyłaniem zmiennej tekstowej przez mplay. Być może ktoś już miał taki kłopot i zna rozwiązanie, albo zna sposób na wysłanie takiej zmiennej (najlepiej przez mplay)?

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ę...