Yoda Opublikowano 14 Lutego 2008 Udostępnij Opublikowano 14 Lutego 2008 Jak działa 39dll? Tak, każdy by chciał stworzyć swój mmorpg, o tak :D W tym tutorialu postaram się wam przybliżyć zasadę działania 39dll oraz przykłady używania najważniejszych funkcji. Na początku chcę zaznaczyć że aby coś zrozumieć musisz być w miarę doświadczony w GMie. Tzn. znajomość zwykłych 'zmiennych' nie wystarczy. Potrzebne będą tablice, zasada działania ID oraz musisz znać podstawy komunikacji server <-> klient. Zacznijmy od podstaw. Działa to w taki sposób - każdy z graczy wysyła dane o sobie na serwer, a ten z kolei rozsyła te dane do innych graczy. Dzięki temu my widzimy co robią inni, a inni widzą co robimy my. A wszystko za pośrednictwem biednego servera którego łącze siada od ilości fanów naszej gry expiących na potworkach =D Tak czy siak, zacznijmy od kliku podstawowych funkcji 39dll: GML dllinit(nazwa dlla, ładowanie funkcji socketow, ładowanie funkcji operacji na plikach); //inicjuje dlla /* nazwa dlla - ustawiamy na 0 jeżeli chcemy użyć domyślnej "39dll.dll" ładowanie funkcji socketow - na true jeżeli chcemy je załadować ( raczej chcemy :P ) ładowanie funkcji operacji na plikach - na true jeżeli chcemy je załadować ( jeżeli potrzebujemy ) */ tcpconnect( ip,port,tryb blokowania ); //proba polaczenia /* ip - adres ip serwera port - port serwera tryb blokowania - domyślnie na true zwraca id socketa */ tcplisten( port, liczba ludzi, tryb blokowania ); //nasluchiwanie na polaczenia ( serwer ) /* port - port na którym ma oczekiwać połączeń liczba ludzi - liczba l. którzy mogą się połączyć tryb blokowania - domyślnie na true zwraca id socketa lub kod błedu */ tcpaccept( socket, tryb blokowania ); //akceptacja polaczenia /* socket - socket z którego nadeszło połączenie tryb blokowania - domyślnie na true zwraca id nowo utworzonego socketa */ closesocket( socket ); /* zamyka i 'czyści' dany socket */ dllfree( ); /* zwalnia dlla z pamięci */ To tyle jeśli chodzi o podłączanie i inicjowanie połączeń. Teraz trochę o przesyłaniu danych i odbieraniu wiadomości. Dane przekazujemy za pomocą kilku prostych funkcji: GML writebyte( wartosc ); /* wysyła 1 bajt. wartość może być pomiędzy 0 a 255 tej funkcji używamy zazwyczaj jeżeli chcemy wysłać ID wiadomości lub gracza. */ writeshort( wartosc ); /* wysyła 2 bajtową wartość liczbową. może być pomiędzy -32768 a +32767 tej z kolei funkcji uzywamy najczesciej do wysylania zmiennych. Jednak jeśli musimy wsłac zmienną mającą większą wartość możemy użyć np. */ writeint( wartosc ); //lub writedouble( wartosc ); /* Jezeli natomiast chcemy wysłac łańcuch znaków ( string ) czyli np. imię gracza albo inną wiadomość tekstową, użyjemy: */ writestring( string ); /* Pamiętaj aby przed wysłaniem pakietu danych użyć funkcji: */ clearbuffer( ); /* Ta funkcja czyści bufor, Aby wysłać nasz pakiet zmiennych czy innych wartości musimy użyć funkcji, odpowiedzialnej za wysłanie wiadomości. Jest to funkcja: */ sendmessage( socket ); /* Wysyła wiadomość do wskazanego przez nas socketa. zwraca liczbę bajtów w wiadomości */ Tak więc przykładowy kod wysyłania danych o naszym graczu na serwer wyglądałby tak: GML clearbuffer( ); //czyscimy bufor writebyte( NAGLOWEK ); //o tym za chwilę writebyte ( naszeID ); // ID naszego gracza writestring ( name ); //zmienna w stringu - imię writeshort( x ); //pozycja x writeshort( y ); //pozycja y wrteshort( life ); //jakaś zmienna - life sendmessage( serversocket ); //wysyłamy wiadomość Teraz o co chodzi, do kurczaczka z tym nagłówkiem nie? Ano, już tłumaczę - każda wysłana wiadomość musi posiadać swoje ID, aby serwer/klient wiedział co robić po odebraniu danej wiadomości. W tym celu używa się 'nagłówków', czyli jakiejś liczby używanej do rozpoznania naszej wiadomości ( ID ). W tym celu najlepiej używać stałych. Dobra, wysłaliśmy nasze wiadomości, ale teraz jak je odebrać? Teraz wytłumaczę najważniejsze funkcje potrzebne przy odbieraniu wiadomości: GML receivemessage( socket ); /* odbiera wiadomość z danego socketa. zwraca liczbę odebranych bajtów */ readbyte( ); /* czyta jeden bajt ( np. ID wiadomosci ) */ readshort( ); /* czyta zmienną short */ readstring( ); /* czyta łańcuch znaków ( string ) */ readint( ); /* czyta zmienną int i tak dalej;) */ Dobra, jak teraz odbieramy wiadomości? Najlepiej oczywiście w stepie. Trzeba w tym celu utworzyć pętlę i odbierać w niej wiadomości z socketa: GML while ( 1 ) { wiadomosc = receivemessage( socket ); //odbieramy wiadomośc if ( wiadomosc <= 0 ) break; //jezeli jest mniejsza bądź równa 0, wyłamujemy się z pętli _ID = readbyte( ); //odbieramy nagłówek wiadomości switch ( _ID ) { case NAGLOWEK: //nagłówek naszej wiadomości { playerID = readbyte( ); //czytamy id gracza który przysłał wiadomość /* teraz należałoby znaleźc ID tego gracza w naszej, np. tablicy graczy */ for ( i=0; i<liczba_graczy; i+=1 ) { if ( i == playerID ) //jeżeli aktualny indeks tablicy równa sie odebranemu ID { with ( i ) { /* odbieramy zmienne */ name = readstring( ); x = readshort( ); y = readshort( ); life = readshort( ); } } } break; } } } Teraz 'gracz' na serwerze odebrał swoje dane. No ale co z innymi graczami? Do nich przecież teraz musimy je wysłać aby oni również zobaczyli zmiany naszego gracza :) No więc w 'kliencie' ( tym na serwerze - odpowiedzialnym za danego gracza w grze ) musimy umieścić taki sam kod jak w kliencie tym na którym gramy, czyli musimy wysłać wiadomości, z tą różnicą, że do innych graczy: GML /* zasada identyczna jak przy wysyłaniu wiadomości z klienta */ clearbuffer( ); writebyte( NAGLOWEK ); writebyte ( naszeID ); writestring ( name ); writeshort( x ); writeshort( y ); wrteshort( life ); with ( objClient ) { if ( clientID != naszeID ) //jezeli ID tego klienta nie równa sie naszemu { sendmessage( playersocket ); //wysyłamy wiadomość } } Teraz należy w kliencie odebrać te wiadomości, a następnie przypisać je obiektowi przedstawiającemu innego gracza. Tak więc w obiekcie odbierającym dane umieszczamy kod podobny jak na serwerze: GML while ( 1 ) { wiadomosc = receivemessage( socket ); //odbieramy wiadomość if ( wiadomosc <= 0 ) break; //jeżeli jest mniejsza bądź równa 0, wyłamujemy się z pętli _ID = readbyte( ); //odbieramy nagłówek wiadomości switch ( _ID ) { case NAGLOWEK: //nagłówek naszej wiadomości { playerID = readbyte( ); //czytamy id gracza który przysłał wiadomośc /* teraz należałoby znaleźc ID tego gracza wśród obiektów przedstawiających innych graczy */ with ( objPlayerOther ) { if ( jegoID == playerID ) //jeżeli ID tego gracza równa sie temu ID które odebraliśmy { /* odbieramy zmienne */ name = readstring( ); x = readshort( ); y = readshort( ); life = readshort( ); } } } break; } } } Tak to mniej więcej wygląda :) Nasz system powinien działać - odbierać zmienne i przekazywać innym graczom. Wydawałoby się że to na razie takie 'nic', ale wierz mi - większość innych rzeczy ( walka, wysyłanie przedmiotów, grafik ) opiera się na tym właśnie co opisałem. Jeżeli to zrozumiesz, nie będziesz miał już problemów. Trzeba się z tym oswoić i trochę potrenować, ale myślę że ten arcik ci to ułatwi. Każde błędy jakie napotkacie w owym tekście zaraz mi reportujcie - czym prędzej poprawię :) Wasz kochający, mastah-plastah Yoda :D EDIT: Jakby co daję w wersji tekstowej http://www.gmclan.org/up2576_4_39dll_tutek.html Sorry że w RTFie, ale dopiero dziś się skumałem że po formacie nie wgrałem OpenOffice'a i na WordPadzie pisałem =D Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
kryniak Opublikowano 14 Lutego 2008 Udostępnij Opublikowano 14 Lutego 2008 No, no! Nieźle napisany. Według mnie powinien zaliczyć dodanie na listę artykułów GMClanu :). Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Administratorzy gnysek Opublikowano 14 Lutego 2008 Administratorzy Udostępnij Opublikowano 14 Lutego 2008 No właśnie czekam na opinię reszty, ale sie zaszyli nagle gdzieś :P To i ja się idę zaszyć, dzisiaj dużo tu zrobiłem :P Borek powinien to przejrzeć, on ma największe doświadczenie :P Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
kryniak Opublikowano 14 Lutego 2008 Udostępnij Opublikowano 14 Lutego 2008 Przydałoby się jeszcze napisać, co poszczególne funkcje zwracają. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Yoda Opublikowano 14 Lutego 2008 Autor Udostępnij Opublikowano 14 Lutego 2008 Hah, zaraz napiszę ;) Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Dawidds Opublikowano 14 Lutego 2008 Udostępnij Opublikowano 14 Lutego 2008 Noo ładnie ;P Aż się zainteresowałęm. Muszę się pobawić z ciekaowści :P Artykuł (o ile działa - a chyba działa...) nadałby się na arty GMC :) Wiem! W nagrodę oejmijcie Yodzie 10% warna xD :P Będzie mał -10% :D Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Yoda Opublikowano 14 Lutego 2008 Autor Udostępnij Opublikowano 14 Lutego 2008 Hah jeszcze dziś miałem 10% =P Btw dodałem opisy co zwracają dane funkcje i dodałem funkcje closesocket( socket ); i dllfreee( ); Zapomniałem sobie o nich a dosyć ważne są ;) Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Nobody Opublikowano 14 Lutego 2008 Udostępnij Opublikowano 14 Lutego 2008 Zaraz ludzie zaczna pisac tutoriale o byle czym, zeby im warny zdjeto ^^ Ale tutek nie powiem, powinien sie przydac. Teraz wiekszosc gier, ktore wyjda to bedzie CTC Online :D Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Sylwester Opublikowano 14 Lutego 2008 Udostępnij Opublikowano 14 Lutego 2008 Zaraz ludzie zaczna pisac tutoriale o byle czym, zeby im warny zdjeto ^^ Ale tutek nie powiem, powinien sie przydac. Teraz wiekszosc gier, ktore wyjda to bedzie CTC Online :D Ale nie za każdy tutek będą mieli odjętego warna,więc pomyśl. Zrób chocby Catch The Clown online to będziesz dobry. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Nobody Opublikowano 14 Lutego 2008 Udostępnij Opublikowano 14 Lutego 2008 Czy sadzisz, ze nie potrafie zrobic prostej Online'owej gierki? Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Yoda Opublikowano 14 Lutego 2008 Autor Udostępnij Opublikowano 14 Lutego 2008 Dobra nie kłóćcie się =P Lepiej mówcie czy toto dobre jest :D Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
kryniak Opublikowano 14 Lutego 2008 Udostępnij Opublikowano 14 Lutego 2008 Czy sadzisz, ze nie potrafie zrobic prostej Online'owej gierki? Chodzi mu o to zapewne, żeby mieć tak głęboką wyobraźnię, żeby z takiej singleplayerowej gierki zrobić multiplayer ;>. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Matthew Opublikowano 14 Lutego 2008 Udostępnij Opublikowano 14 Lutego 2008 Gdy mówiłem o tłumaczeniu 39dll, miałem na myśli GaduGadu... Sorki, że nie było mnie wtedy - komp był zajęty :3 Kiedy obcykam tutka to zabiorę się w końcu za swoją gierkę. BTW. Do artu można dodać jeszcze spolszczoną tabelkę z mojego uploadera. Pisze tam ile miejsca zajmują poszczególne typy zmiennych. Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Marek.S Opublikowano 15 Lutego 2008 Udostępnij Opublikowano 15 Lutego 2008 Yoda, masz u mnie browara :D Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Nobody Opublikowano 15 Lutego 2008 Udostępnij Opublikowano 15 Lutego 2008 Chodzi mu o to zapewne, żeby mieć tak głęboką wyobraźnię, żeby z takiej singleplayerowej gierki zrobić multiplayer ;>. Juz sobie to wyobrazam ^^ Playerzy jako kursory myszki, po zderzeniu sie od siebie odbijaja i walcza, zeby kliknac tego biednego klauna ^^ Tryby: Czasowy, do ilustam punktow, Capture the Clown (CTF tylko na klaunach ^^)... :P Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Yoda Opublikowano 15 Lutego 2008 Autor Udostępnij Opublikowano 15 Lutego 2008 Yoda, masz u mnie browara biggrin.gif to kiedy wpadasz do Katowic? :cheers: Do artu można dodać jeszcze spolszczoną tabelkę z mojego uploadera. Pisze tam ile miejsca zajmują poszczególne typy zmiennych. Ok dodam za chwilkę ;) Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Nx Opublikowano 16 Lutego 2008 Udostępnij Opublikowano 16 Lutego 2008 Tutek fajny dałbym 5/5 @yoda Ja mogę wpaść do katowic Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
swety Opublikowano 16 Lutego 2008 Udostępnij Opublikowano 16 Lutego 2008 Veri nice ! :D :) Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Nobody Opublikowano 16 Lutego 2008 Udostępnij Opublikowano 16 Lutego 2008 Yoda, miales wrzucic tabelke z wielkosciami zmiennych :P Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
kryniak Opublikowano 16 Lutego 2008 Udostępnij Opublikowano 16 Lutego 2008 Dopisz może: zwraca id socketa, którego będziemy używać w pozostałych funkcjach :P Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Crackkk-GM Opublikowano 16 Lutego 2008 Udostępnij Opublikowano 16 Lutego 2008 Tak więc przykładowy kod wysyłania danych o naszym graczu na serwer wyglądałby tak: GML clearbuffer( ); //czyscimy bufor writebyte( NAGLOWEK ); //o tym za chwilę writebyte ( naszeID ); // ID naszego gracza writestring ( name ); //zmienna w stringu - imię writeshort( x ); //pozycja x writeshort( y ); //pozycja y wrteshort( life ); //jakaś zmienna - life sendmessage( serversocket ); //wysyłamy wiadomość Wyłapałem błąd :P Tutek się przyda ^^ PS: Yoda powiedz mi jak wysłać pozycję sprita Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Yoda Opublikowano 16 Lutego 2008 Autor Udostępnij Opublikowano 16 Lutego 2008 Yoda powiedz mi jak wysłać pozycję sprita Pozycji sprita się nie wysyła. Yoda, miales wrzucic tabelke z wielkosciami zmiennych tongue2.gif Damn, zapomniałem :F Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Crackkk-GM Opublikowano 16 Lutego 2008 Udostępnij Opublikowano 16 Lutego 2008 Tzn nie sprita tylko podczas animacji ruchu, żeby było widać jak się porusza ;p Ok, już wiem xD Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
pablo1517 Opublikowano 16 Lutego 2008 Udostępnij Opublikowano 16 Lutego 2008 Po co wam ta tabelka? W funkcjach dll'a jest napisane ile bajtów wysyła dana funkcja... poza tym... może by tak trochę własnej wiedzy, a nie wszystko na gotowcach :/. Wikipedia nie boli. Art dobry, tylko razi mnie te "kod błędu". Lepiej napisać, że w razie nie powodzenia zwraca pusty string lub -1 Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Morrighan (AoM) Opublikowano 16 Lutego 2008 Udostępnij Opublikowano 16 Lutego 2008 Art bardzo mnie się spodobał, Yoda, odwaliłeś kawał dobrej roboty :) Z całą pewnością wielu tutaj osobom się przyda... w tym i mnie :) Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Nobody Opublikowano 17 Lutego 2008 Udostępnij Opublikowano 17 Lutego 2008 Hmmm... Co myslicie o wysylaniu wszystkich danych za pomoca jednego writebyte i jednego stringa? np: writebyte(20); (funkcja update'ujaca pozycje) writestring(string(x)+'|'+string(y)+'|'+string(image_angle)); A na serwerze rozdzielanie tego z powrotem na zmienne? Czy dzieki temu uniknalbym wysylania zbyt wielu bajtow? Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Misiek999 Opublikowano 17 Lutego 2008 Udostępnij Opublikowano 17 Lutego 2008 nom to jest dobry sposób imo :D Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
kubasz Opublikowano 17 Lutego 2008 Udostępnij Opublikowano 17 Lutego 2008 Hmmm... Co myslicie o wysylaniu wszystkich danych za pomoca jednego writebyte i jednego stringa? np: writebyte(20); (funkcja update'ujaca pozycje) writestring(string(x)+'|'+string(y)+'|'+string(image_angle)); A na serwerze rozdzielanie tego z powrotem na zmienne? Czy dzieki temu uniknalbym wysylania zbyt wielu bajtow? W Ultimate MPlay przesyłał(MPLAY) id jako 1 i zapisywał ten id co ty podałeś do messagea. później jakoś to rozpakowywał (Wszystko do jednego real!!!) Dokładnie nie analizowałem tej jednej lini kodu! - KUB@SZ Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Boro Casso Opublikowano 17 Lutego 2008 Udostępnij Opublikowano 17 Lutego 2008 Mnie i tak 39dll nie przekonuje, wole soc ;) Odnośnik do komentarza Udostępnij na innych stronach Więcej opcji udostępniania...
Pentalinio Opublikowano 17 Lutego 2008 Udostępnij Opublikowano 17 Lutego 2008 Ale wtedy odczyt wyglądałby chyba tak: GML _s = readstring(); _i = 1; _temp = _i; while( true ) { if ( string_char_at( _s, _i ) == '|' ) { x = real( string_copy( _s, _temp, _i ) ); _temp = _i + 1; break; } _i += 1; } while( true ) { if ( string_char_at( _s, _i ) == '|' ) { y = real( string_copy( _s, _temp, _i ) ); _temp = _i + 1; break; } _i += 1; } while( true ) { if ( _i = string_length( _s ) ) { image_angle = real( string_copy( _s, _temp, _i ) ); break; } _i += 1; } A to byłoby imo głupie :/ . 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ę