Ten artykuł został stworzony dla starszych wersji GameMakera i może nie być aktualny.

Podstawy tworzenia gier online z 39dll

Piątek, 15 Lutego 2008, 20:13
Czas czytania 5 minut, 35 sekund
Zgodne z GM: gm5 gm6 gm7 gm8
W tym tutorialu postaram się wam przybliżyć zasadę działania 39dll oraz przykłady używania najważniejszych funkcji, przydatnych do tworzenia gier online.
Każdy by chciał stworzyć swój mmorpg - 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 do zrozumienia treści tego artykułu wymagana jest dość dobra znajomość GML. Tzn. znajomość zwykłych 'zmiennych' nie wystarczy. Potrzebne będą tablice, zasada działania ID oraz podstawy komunikacji serwer - klient.

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 serwera którego łącze siada od ilości fanów naszej gry exp-iących na potworkach. Tak czy siak, zacznijmy od kliku podstawowych funkcji 39dll:

koddllinit(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 tongue2.gif )
ł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:

kodwritebyte( 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:

kodclearbuffer( ); //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ść

Czym jest NAGLOWEK ? 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:

kodreceivemessage( 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:

kodwhile ( 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:

kod/* 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:

kodwhile ( 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 artykuł ci to ułatwi.
Komentarze (łącznie 32, wyświetlam 1 - 15):
Misiek999 (Pią., 15 Lut. 08, 20:15)
#1

no i cud miód malina :]

Yoho (Pią., 15 Lut. 08, 20:18)
#2

a nawet wyglądające jak ciasteczka, smakujące jak ciasteczka pyszne płatki śniadaniowe Coooookie Criisp!

Y
Yoda (Pią., 15 Lut. 08, 20:19)
#3

Ej Yoho wyjdź stąd ;|

Misiek999 (Pią., 15 Lut. 08, 20:22)
#4

Yoda on wyraża w ten sposób swoje emocje po przeczytaniu tego arta w taki gangsterski sposób.

Y
Yoda (Pią., 15 Lut. 08, 20:25)
#5

Aaa no tak. A i Coookie crisps są niedobre. Lepsze miodowe kółeczka nestle Cherioos =3

Misiek999 (Pią., 15 Lut. 08, 20:30)
#6

a ja w ogóle nie jadam płatków śniadaniowych bo nie wiem czemu straszne potem mam gazy po nich ;[

Borek (Pią., 15 Lut. 08, 20:40)
#7

Dobra już nie spamujcie.

Matthew (Pią., 15 Lut. 08, 20:52)
#8

Cini Minis rządzą!!!

Co do arta: na pewno się przyda tym, którzy UMIEJĄ robić przyzwoite gry. Jak tylko pojawi się CtC online to stawiam twórcy jedynkę (tj. jedną gwiazdkę) i włączę drugie konto i też postawię gałę!!!

Misiek999 (Pią., 15 Lut. 08, 20:57)
#9

a co to jego wina że ktoś wykorzysta art do niecnych czynów ? :D

Y
Yoda (Pią., 15 Lut. 08, 20:57)
#10

Tzn.powiem tak: początkujący i tak nic nie skuma ;3 Trzeba znać te tablice, zasady pętli i adresowania przez id ;)

Matthew (Pią., 15 Lut. 08, 21:04)
#11

@Misiek999: mówiąc "twórcy" miałem na myśli twórcę CtCO.

Właśnie przeczytałem art i zrozumiałem 80% Jak będę robił gierkę to się wkuję. BTW. jest błąd z emotikonką tongue2.gif w tym nawiasie "raczej chcemy".

Y
Yoda (Pią., 15 Lut. 08, 21:06)
#12

ładniej by wyglądało jakby kod był pokolorowany i były tabulacje ;P

Y
Yoda (Pią., 15 Lut. 08, 21:07)
#13

Dla mnie czytelność kodu to podstawa w zrozumieniu jego działania i łatwej edycji :)

P
PsichiX (Pią., 15 Lut. 08, 21:48)
#14

A ja bede inny i powiem ze mogles lepiej wytlumaczyc w tym tutku ;P Ale i tak dobrze, widac ze sporo umiesz i twoja wiedza przyda sie innym.

Y
Yoda (Pią., 15 Lut. 08, 22:17)
#15

Hah jeśli chodzi o "wytłumaczanie" to nie jestem w tym najlepszy :P

Najnowsze wersje GameMakera:

Stabilna
2024.2.0.132 • 2024.2.0.163
wydana 15 dni temu
LTS
2022.0.2.51 • 2022.0.2.49
wydana 154 dni temu
Beta
2024.400.0.516 • 2024.400.0.537
wydana  5 dni temu
= IDE, = Runtime
Użytkownicy online
1 użytkownik aktywny:
gości: 1,
(~ostatnie 15 minut)
Discord
23 użytkownicy online na discordzie:
DungeonFairy🧚, s..., Alice, Nitro Slav, Carl-bot, p..., Add92, SuperEnduro, Kuzyn, Filyps, fervi, YoungKrystian, Kalor, r..., 🧁Cupcake🧁, antek, Pako, Arrekin, Dyno, Ulti, bagno, g..., Shockah
Shoutbox
I am Lord (19:15, 17.03.24)
6h mam na to hmmm
I am Lord (19:06, 17.03.24)
Ale temat fajny
gnysek (01:33, 13.03.24)
Powinno działać, jest w kodzie sortowanie wg. najbliższego startu :)
Uzjel (21:59, 11.03.24)
Nie, ale za pierwszym razem zrobiłem fuckup, że było "Tura testowa" X_X
I am Lord (16:58, 11.03.24)
A co Uzjel już masz nawymyślane 100 tematów? 😅
Uzjel (20:08, 10.03.24)
@gnysek a jak bym dodał kilka lig na raz to walnie?
Uzjel (20:08, 10.03.24)
Liga będzie zawsze od piątku 16:00 do poniedziałku 23:59, zawsze w środku miesiąca.
gnysek (08:48, 10.03.24)
Tak, to też jest do poprawy X_X
Adriann (18:22, 09.03.24)
Tylko myślę czy nie leiej gdyby mówiło że zostało tyle i tyle dni i ileś godzin a nie tylko w godzinach ;d Albo konkretna data obok, byłoby czytelniej
I am Lord (15:08, 08.03.24)
o super z tą ligą :)
Starsze wpisy znajdziesz w Archiwum.
Ankieta
Ile zarobiłeś do tej pory na grach stworzonych w GM?