Jemkam Opublikowano 15 Września 2013 Udostępnij Opublikowano 15 Września 2013 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 Więcej opcji udostępniania...
Administratorzy gnysek Opublikowano 15 Września 2013 Administratorzy Udostępnij Opublikowano 15 Września 2013 A sam kod? Bo tak to ciężko wróżyć z fusów, ale wygląda ze nie do tego gracza dane wysyłasz. Albo nie rozróżniasz niczego po jakiejś fladze/id. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Jemkam Opublikowano 15 Września 2013 Autor Udostępnij Opublikowano 15 Września 2013 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 Więcej opcji udostępniania...
Administratorzy gnysek Opublikowano 16 Września 2013 Administratorzy Udostępnij Opublikowano 16 Września 2013 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 Więcej opcji udostępniania...
Jemkam Opublikowano 17 Września 2013 Autor Udostępnij Opublikowano 17 Września 2013 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 Więcej opcji udostępniania...
Administratorzy gnysek Opublikowano 17 Września 2013 Administratorzy Udostępnij Opublikowano 17 Września 2013 No to nie wiem gdzie nie działa. Może nadawanie numerów na początku źle działa? Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Jemkam Opublikowano 17 Września 2013 Autor Udostępnij Opublikowano 17 Września 2013 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 Więcej opcji udostępniania...
Jemkam Opublikowano 28 Września 2013 Autor Udostępnij Opublikowano 28 Września 2013 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 Więcej opcji udostępniania...
lenin Opublikowano 29 Września 2013 Udostępnij Opublikowano 29 Września 2013 GML i=instance_number(obiekt) o=instance_create(x,y,obiekt) o.zmienna=0 pierwszy obiekt to o[0] Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Jemkam Opublikowano 30 Września 2013 Autor Udostępnij Opublikowano 30 Września 2013 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 Więcej opcji udostępniania...
Administratorzy gnysek Opublikowano 30 Września 2013 Administratorzy Udostępnij Opublikowano 30 Września 2013 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 Więcej opcji udostępniania...
Jemkam Opublikowano 30 Września 2013 Autor Udostępnij Opublikowano 30 Września 2013 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 Więcej opcji udostępniania...
Administratorzy gnysek Opublikowano 1 Października 2013 Administratorzy Udostępnij Opublikowano 1 Października 2013 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 Więcej opcji udostępniania...
Jemkam Opublikowano 1 Października 2013 Autor Udostępnij Opublikowano 1 Października 2013 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 Więcej opcji udostępniania...
Administratorzy gnysek Opublikowano 1 Października 2013 Administratorzy Udostępnij Opublikowano 1 Października 2013 Używasz polskich znaków w imionach? Btw. ja bym się w mplay nie bawił, jest mocno, mocno ograniczony. 39dll, albo bufory ktore wprowadza GM:S. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Jemkam Opublikowano 1 Października 2013 Autor Udostępnij Opublikowano 1 Października 2013 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 Więcej opcji udostępniania...
Jemkam Opublikowano 3 Października 2013 Autor Udostępnij Opublikowano 3 Października 2013 Ogólnie zauważyłem, że błąd jest w podpisywaniu zmiennej imie_gracza pod zmienną mplay. Może problem jest z tym, że mplay nie współgra z get_string? Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Administratorzy gnysek Opublikowano 3 Października 2013 Administratorzy Udostępnij Opublikowano 3 Października 2013 To podstaw za GML imie_gracza=get_string("Imie gracza : ",""); GML imie_gracza = "Gracz " + string(numer_gracza); Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Jemkam Opublikowano 3 Października 2013 Autor Udostępnij Opublikowano 3 Października 2013 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 Więcej opcji udostępniania...
Jemkam Opublikowano 11 Października 2013 Autor Udostępnij Opublikowano 11 Października 2013 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 Więcej opcji udostępniania...
Rekomendowane odpowiedzi
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ę